Pivot Tables of Counts in Pandas DataFrame

Question:

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?

Asked By: SteelyDanish

||

Answers:

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
Answered By: Zero

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)

transformation

Answered By: cottontail