Bowen Peng
Bowen Peng

Reputation: 1815

How to do value_counts on each row and make some columns whose values are the counts of each value

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.

Upvotes: 3

Views: 8337

Answers (3)

BENY
BENY

Reputation: 323226

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

Upvotes: 4

tawab_shakeel
tawab_shakeel

Reputation: 3739

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

Upvotes: 3

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

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

Upvotes: 2

Related Questions