1

I get a dataframe as follows:

df
     c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12
r1   0   1   1   1   1   0   0   0   0   0   0   0
r2   1   2   2   2   2   1   1   1   1   0   0   0      
r3   1   0   2   0   0   1   0   0   0   0   0   0      


func(df)
     0   1   2
r1   8   4   0
r2   3   5   4
r3   9   2   1

And I want to do value_counts on each row and get 3 columns which are corresponding to the count of each value.
What I thought is to do melt() in each row, get values counts and fill it in corresponding place. BUT I think it is not a smart and convenient enough way.
So if not mind could anyone help me?
Thanks in advance.

Bowen Peng
  • 1,437
  • 3
  • 15
  • 31
  • 2
    Do not using apply please https://stackoverflow.com/questions/54432583/when-should-i-ever-want-to-use-pandas-apply-in-my-code – BENY Jul 28 '19 at 15:40

3 Answers3

2

Here is one way

df.stack().groupby(level=0).value_counts().unstack(fill_value=0)
    0  1  2
r1  8  4  0
r2  3  5  4
r3  9  2  1

And with crosstab should be fast:-)

s=df.reset_index().melt('index')
pd.crosstab(s['index'],s.value)
value  0  1  2
index         
r1     8  4  0
r2     3  5  4
r3     9  2  1
BENY
  • 296,997
  • 19
  • 147
  • 204
2

Straightforwardly (with Dataframe.apply + pandas.Series.value_counts):

In [232]: df.apply(lambda s: s.value_counts(), axis=1).fillna(0)                                                  
Out[232]: 
      0    1    2
r1  8.0  4.0  0.0
r2  3.0  5.0  4.0
r3  9.0  2.0  1.0
RomanPerekhrest
  • 75,918
  • 4
  • 51
  • 91
2

try using simple pd.Series.value_counts and fillna with 0

df.apply(pd.Series.value_counts, axis=1).fillna(0)
     0   1   2
r1   8   4   0
r2   3   5   4
r3   9   2   1
tawab_shakeel
  • 3,541
  • 8
  • 25
  • 1
    Please try not using apply , for more info https://stackoverflow.com/questions/54432583/when-should-i-ever-want-to-use-pandas-apply-in-my-code – BENY Jul 28 '19 at 15:40
  • @WeNYoBen ok I'll try not to use apply in future.Thanks for the suggestion :) – tawab_shakeel Jul 28 '19 at 15:42