Décompresser et compter les valeurs de retour pour chaque variable?

19

J'ai une base de données qui enregistre les réponses du choix des langues de programmation par 19717 personnes à travers des questions à choix multiples. La première colonne est bien sûr le sexe du répondant tandis que les autres sont les choix qu'ils ont choisis. Et donc si je choisis Python, ma réponse sera enregistrée dans la colonne Python et non bash et 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

Ce que je veux, c'est un tableau qui renvoie le nombre d'instances de chaque catégorie sous les Genderenregistrements. Par conséquent, si 5000 hommes codés en Python et 3000 femmes en JS, je devrais obtenir ceci:

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

J'ai essayé certaines des options:

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

Et ce n'est pas ce qui est requis comme décrit ci-dessus. Cela peut-il être fait chez les pandas?

Shiv_90
la source

Réponses:

7

Une autre idée serait de faire des valeurs le long de l'axe 1, puis :apply joinget_dummiesgroupby

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

[en dehors]

                   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
la source
7

Vous pouvez définir Gendercomme index et somme:

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

Production:

                   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
la source
Pour une raison quelconque, cela renvoie tous les 0 pour chaque Genderindex.
Shiv_90
4

Supposons que votre nanest NaN(c'est-à-dire qu'il ne s'agit pas d'une chaîne), nous pouvons en profiter countcar il l'ignore NaNpour obtenir la sortie souhaitée

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.
la source
3

Vous pouvez meltet utilisezcrosstab

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
la source
2

Poussons à une seule ligne

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
la source