multiple groupby example columns agg python pandas numpy group-by pandas-groupby

python - groupby - Cuente el número de resultados de escala de Likert de preguntas de columna múltiple en pandas



python group by agg (3)

Tengo el siguiente marco de datos:

Question1 Question2 Question3 Question4 User1 Agree Agree Disagree Strongly Disagree User2 Disagree Agree Agree Disagree User3 Agree Agree Agree Agree

¿Hay alguna manera de convertir el marco de datos enumerado anteriormente a lo siguiente?

Agree Disagree Strongly Disagree Question1 2 1 0 Question2 2 1 0 Question3 2 1 0 Question4 1 1 1

Esto es similar a mi pregunta anterior: crear un marco de datos con preguntas agrupadas de tres columnas

Traté de ver las preguntas anteriores con pila / pivote pero no pude entenderlo. El marco de datos real tiene más de 20 preguntas y una escala Likert de totalmente de acuerdo, de acuerdo, neutral, en desacuerdo, totalmente en desacuerdo.


Con pd.get_dummies

pd.get_dummies(df.stack()).groupby(level=1).sum() Agree Disagree Strongly Disagree Question1 2 1 0 Question2 3 0 0 Question3 2 1 0 Question4 1 1 1

Llevarlo a otro nivel
Podemos usar numpy.bincount para acelerar las cosas. Pero debemos prestar atención a las dimensiones

v = df.values f, u = pd.factorize(v.ravel()) n, m = u.size, v.shape[1] r = np.tile(np.arange(m), n) b0 = np.bincount(r * n + f) pad = np.zeros(n * m - b0.size, dtype=int) b = np.append(b0, pad) pd.DataFrame(b.reshape(m, n), df.columns, u) Agree Disagree Strongly Disagree Question1 2 1 0 Question2 3 0 0 Question3 2 1 0 Question4 1 1 1

Otra opción numpy

v = df.values n, m = v.shape f, u = pd.factorize(v.ravel()) pd.DataFrame( np.eye(u.size, dtype=int)[f].reshape(n, m, -1).sum(0), df.columns, u ) Agree Disagree Strongly Disagree Question1 2 1 0 Question2 3 0 0 Question3 2 1 0 Question4 1 1 1

Diferencia de velocidad

%%timeit v = df.values f, u = pd.factorize(v.ravel()) n, m = u.size, v.shape[1] r = np.tile(np.arange(m), n) b0 = np.bincount(r * n + f) pad = np.zeros(n * m - b0.size, dtype=int) b = np.append(b0, pad) ​ pd.DataFrame(b.reshape(m, n), df.columns, u) 1000 loops, best of 3: 194 µs per loop %%timeit v = df.values n, m = v.shape f, u = pd.factorize(v.ravel()) pd.DataFrame( np.eye(u.size, dtype=int)[f].reshape(n, m, -1).sum(0), df.columns, u ) 1000 loops, best of 3: 195 µs per loop %timeit pd.get_dummies(df.stack()).groupby(level=1).sum() 1000 loops, best of 3: 1.2 ms per loop


Puede iterar sobre columnas con pd.Series.value_counts . Si hace esto con aplicar, los índices se alinearán automáticamente:

df.apply(pd.Series.value_counts) Out: Question1 Question2 Question3 Question4 Agree 2.0 3.0 2.0 1 Disagree 1.0 NaN 1.0 1 Strongly Disagree NaN NaN NaN 1

Un poco de postprocesamiento:

df.apply(pd.Series.value_counts).fillna(0).astype(''int'') Out: Question1 Question2 Question3 Question4 Agree 2 3 2 1 Disagree 1 0 1 1 Strongly Disagree 0 0 0 1


df.apply(lambda x:x.value_counts()).fillna(0).astype(int) # Question1 Question2 Question3 Question4 #Agree 2 3 2 1 #Disagree 1 0 1 1 #Strongly Disagree 0 0 0 1