¿Desapilar y devolver valor cuenta para cada variable?

19

Tengo un marco de datos que registra las respuestas de la elección de lenguajes de programación de 19717 personas a través de preguntas de opción múltiple. La primera columna es, por supuesto, el género del encuestado, mientras que el resto son las opciones que eligieron. Y, por lo tanto, si elijo Python, mi respuesta se registrará en la columna de Python y no en bash y viceversa.

ID     Gender              Python    Bash    R    JavaScript    C++
0      Male                Python    nan     nan  JavaScript    nan
1      Female              nan       nan     R    JavaScript    C++
2      Prefer not to say   Python    Bash    nan  nan           nan
3      Male                nan       nan     nan  nan           nan

Lo que quiero es una tabla que devuelva el número de instancias de cada categoría en los Genderregistros. Por lo tanto, si 5000 hombres codificaron en Python y 3000 mujeres en JS, entonces debería obtener esto:

Gender              Python    Bash    R    JavaScript    C++
Male                5000      1000    800  1500          1000
Female              4000      500     1500 3000          800
Prefer Not To Say   2000      ...   ...    ...           860

He probado algunas de las opciones:

df.iloc[:, [*range(0, 13)]].stack().value_counts()

Male                       16138
Python                     12841
SQL                         6532
R                           4588
Female                      3212
Java                        2267
C++                         2256
Javascript                  2174
Bash                        2037
C                           1672
MATLAB                      1516
Other                       1148
TypeScript                   389
Prefer not to say            318
None                          83
Prefer to self-describe       49
dtype: int64

Y no es lo que se requiere como se describe anteriormente. ¿Se puede hacer esto en pandas?

Shiv_90
fuente

Respuestas:

7

Otra idea sería valores a lo largo del eje 1, entonces :apply joinget_dummiesgroupby

(df.loc[:, 'Python':]
 .apply(lambda x: '|'.join(x.dropna()), axis=1)
 .str.get_dummies('|')
 .groupby(df['Gender']).sum())

[fuera]

                   Bash  C++  JavaScript  Python  R
Gender                                             
Female                0    1           1       0  1
Male                  0    0           1       1  0
Prefer not to say     1    0           0       1  0
Chris A
fuente
7

Puede establecer Gendercomo índice y suma:

s = df.set_index('Gender').iloc[:, 1:]
s.eq(s.columns).astype(int).sum(level=0)

Salida:

                   Python  Bash  R  JavaScript  C++
Gender                                             
Male                    1     0  0           1    0
Female                  0     0  1           1    1
Prefer not to say       1     1  0           0    0
Quang Hoang
fuente
Por alguna razón, esto devuelve todos los ceros para cada Genderíndice.
Shiv_90
4

Supongamos que su nanes NaN( es decir, no es una cadena), podemos aprovechar countporque ignora NaNpara obtener la salida deseada

df_out = df.iloc[:,2:].groupby(df.Gender, sort=False).count()

Out[175]:
                   Python  Bash  R  JavaScript  C++
Gender
Male                    1     0  0           1    0
Female                  0     0  1           1    1
Prefer not to say       1     1  0           0    0
Andy L.
fuente
3

Puedes melty usascrosstab

df1 = pd.melt(df,id_vars=['ID','Gender'],var_name='Language',value_name='Choice')
df1['Choice'] = np.where(df1['Choice'] == df1['Language'],1,0)
final= pd.crosstab(df1['Gender'],df1['Language'],values=df1['Choice'],aggfunc='sum')

print(final)
Language              Bash  C++  JavaScript  Python  R
Gender                                              
Female                  0    1           1       0  1
Male                    0    0           1       1  0
Prefer not to say       1    0           0       1  0
Datanovice
fuente
2

Pasemos a una línea

df.drop('ID',1).melt('Gender').\
    query('variable==value').\
      groupby(['Gender','variable']).size().unstack(fill_value=0)
Out[120]: 
variable        Bash  C++  JavaScript  Python  R
Gender                                          
Female             0    1           1       0  1
Male               0    0           1       1  0
Prefernottosay     1    0           0       1  0
YOBEN_S
fuente