Reputation: 669
I have a pandas dataframe:
Col X Col Y
class 1 cat 1
class 2 cat 1
class 3 cat 2
class 2 cat 3
that I want to transform into:
cat 1 cat 2 cat 3
class 1 1 0 0
class 2 1 0 1
class 3 0 1 0
where the values are value counts. How do I do it?
Upvotes: 45
Views: 45947
Reputation: 23271
Since pandas 1.1.0, value_counts()
can be called on a dataframe. So another way is to count each pairs of Col X-Col Y values and unstack the counts.
table = df[['Col X', 'Col Y']].value_counts().rename_axis([None, None]).unstack(fill_value=0)
Upvotes: 1
Reputation: 76947
Here are couple of ways to reshape your data df
In [27]: df
Out[27]:
Col X Col Y
0 class 1 cat 1
1 class 2 cat 1
2 class 3 cat 2
3 class 2 cat 3
1) Using pd.crosstab()
In [28]: pd.crosstab(df['Col X'], df['Col Y'])
Out[28]:
Col Y cat 1 cat 2 cat 3
Col X
class 1 1 0 0
class 2 1 0 1
class 3 0 1 0
2) Or, use groupby
on 'Col X','Col Y'
with unstack
over Col Y
, then fill NaNs
with zeros.
In [29]: df.groupby(['Col X','Col Y']).size().unstack('Col Y', fill_value=0)
Out[29]:
Col Y cat 1 cat 2 cat 3
Col X
class 1 1 0 0
class 2 1 0 1
class 3 0 1 0
3) Or, use pd.pivot_table()
with index=Col X
, columns=Col Y
In [30]: pd.pivot_table(df, index=['Col X'], columns=['Col Y'], aggfunc=len, fill_value=0)
Out[30]:
Col Y cat 1 cat 2 cat 3
Col X
class 1 1 0 0
class 2 1 0 1
class 3 0 1 0
4) Or, use set_index
with unstack
In [492]: df.assign(v=1).set_index(['Col X', 'Col Y'])['v'].unstack(fill_value=0)
Out[492]:
Col Y cat 1 cat 2 cat 3
Col X
class 1 1 0 0
class 2 1 0 1
class 3 0 1 0
Upvotes: 96