Tengo un df con esta estructura:
id a1_l1 a2_l1 a3_l1 a1_l2 a2_l2 a3_l2 1 1 5 3 1 2 3 2 1 5 3 1 2 3 3 2 5 3 5 5 3 4 5 5 3 5 5 3 5 5 5 2 6 5 5 2 7 5 5 2 8 2 5 2 9 3 5 1 10 3 5 1Quiero resumir en una tabla tal que obtengo:
l1 l2 a1 0.4 0.5 a2 1 0.5 a3 0 0En el que lo que estoy haciendo es contar cuántas veces 5 estuvo presente dividido por el número de respuestas válidas, de modo que, por ejemplo:
a1, l1 es igual a 0,4 ya que tengo 4 valores de 5 divididos por 10. y a2, l1 es igual a 0,5 ya que tengo 2 valores de 5 divididos por 4 respuestas válidas por columna.
¡Gracias!
También puede soltar la columna id drop('id', axis=1) en lugar de set_index('id')
(x == 5).sum() / x.notna().sum() tmp = df.set_index('id').apply(lambda x: x.eq(5).sum()/x.notna().sum()).reset_index() tmp[['a', 'l']] = tmp['index'].str.split('_', expand=True) >>> index 0 al 0 a1_l1 0.4 a1 l1 1 a2_l1 1.0 a2 l1 2 a3_l1 0.0 a3 l1 3 a1_l2 0.5 a1 l2 4 a2_l2 0.5 a2 l2 5 a3_l2 0.0 a3 l2 tmp.drop('index', axis=1).pivot(index='a', columns='l').droplevel(0, axis=1).rename_axis(None).rename_axis(None, axis=1) >>> l1 l2 a1 0.4 0.5 a2 1.0 0.5 a3 0.0 0.0Prueba con pd.wide_to_long
s = pd.wide_to_long(df,['a1','a2','a3'],i='id',j = 'level',sep='_',suffix='\\w+') out = s.eq(5).groupby(level=1).sum() out = out.T.div(s.groupby(level=1).size()) out level l1 l2 a1 0.4 0.2 a2 1.0 0.2 a3 0.0 0.0Puede remodelar para tener un marco de datos con MultiIndex, luego realizar una división simple de ( sum de los valores verdaderos igual a 5) por no na. Finalmente, unstack :
df2 = df.set_index('id') df2.columns = df2.columns.str.split('_', expand = True) df2 = (df2.eq(5).sum()/df2.notna().sum()).unstack()producción:
l1 l2 a1 0.4 0.5 a2 1.0 0.5 a3 0.0 0.0