Rozpakować i zwrócić wartość liczy się dla każdej zmiennej?

19

Mam ramkę danych, która rejestruje odpowiedzi 19717 osób na wybór języków programowania za pomocą pytań wielokrotnego wyboru. Pierwsza kolumna to oczywiście płeć respondenta, a reszta to wybory, które wybrali. Dlatego jeśli wybiorę Python, moja odpowiedź zostanie zapisana w kolumnie Python, a nie bash i odwrotnie.

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

Chcę tabeli, która zwraca liczbę wystąpień każdej kategorii w Genderrekordach. Dlatego jeśli 5000 mężczyzn zakodowanych w Pythonie i 3000 kobiet w JS, powinienem uzyskać:

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

Wypróbowałem niektóre z opcji:

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

I nie jest to wymagane, jak opisano powyżej. Czy można to zrobić w pandach?

Shiv_90
źródło

Odpowiedzi:

7

Innym pomysłem byłyby wartości wzdłuż osi 1, a następnie :apply joinget_dummiesgroupby

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

[na zewnątrz]

                   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.
źródło
7

Możesz ustawić Genderjako indeks i sumę:

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

Wynik:

                   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
źródło
Z jakiegoś powodu zwraca wszystkie zera dla każdego Genderindeksu.
Shiv_90
4

Załóżmy, że twoja nanjest NaN(tzn. Nie jest łańcuchem), możemy skorzystać, countponieważ ignoruje NaNona uzyskanie pożądanego wyniku

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.
źródło
3

Możesz melti używaszcrosstab

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
źródło
2

Przejdźmy do jednej linii

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
źródło