Reputation: 1815
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
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
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
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