Desempilhar e retornar o valor conta para cada variável?

19

Eu tenho um quadro de dados que registra respostas da escolha de 19717 pessoas das linguagens de programação por meio de perguntas de múltipla escolha. A primeira coluna é, obviamente, o sexo do entrevistado, enquanto o restante são as escolhas que eles escolheram. E, portanto, se eu escolher o Python, minha resposta será registrada na coluna Python, e não no bash e vice-versa.

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

O que eu quero é uma tabela que retorne o número de instâncias de cada categoria nos Genderregistros. Portanto, se 5000 homens codificados em Python e 3000 mulheres em JS, então eu deveria obter o seguinte:

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

Eu tentei algumas das opções:

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

E não é o necessário, conforme descrito acima. Isso pode ser feito em pandas?

Shiv_90
fonte

Respostas:

7

Outra idéia seria valores ao longo do eixo 1, então :apply joinget_dummiesgroupby

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

[Fora]

                   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
fonte
7

Você pode definir Gendercomo índice e soma:

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

Resultado:

                   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
fonte
Por alguma razão, isso está retornando todos os 0s para cada Genderíndice.
Shiv_90
4

Suponha que você nané NaN(ou seja, não é uma string), podemos tirar vantagem countporque ignora NaNpara obter a saída desejada

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.
fonte
3

Você pode melte usarcrosstab

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
fonte
2

Vamos avançar para uma linha

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
fonte