Get a frequency count based on multiple dataframe columns
Asked Answered
H

3

152

I have the following dataframe.

Group Size
Short Small
Short Small
Moderate Medium
Moderate Small
Tall Large

I want to count the frequency of how many times the same row appears in the dataframe.

Group           Size      Time
Short          Small        2
Moderate       Medium       1 
Moderate       Small        1
Tall           Large        1
Hobard answered 21/10, 2015 at 23:41 Comment(1)
Note on performance, including alternatives: Pandas groupby.size vs series.value_counts vs collections.Counter with multiple seriesRhyner
E
209

You can use groupby's size

import pandas as pd

# load the sample data
data = {'Group': ['Short', 'Short', 'Moderate', 'Moderate', 'Tall'], 'Size': ['Small', 'Small', 'Medium', 'Small', 'Large']}
df = pd.DataFrame(data)

Option 1:

dfg = df.groupby(by=["Group", "Size"]).size()

# which results in a pandas.core.series.Series
Group     Size
Moderate  Medium    1
          Small     1
Short     Small     2
Tall      Large     1
dtype: int64

Option 2:

dfg = df.groupby(by=["Group", "Size"]).size().reset_index(name="Time")

# which results in a pandas.core.frame.DataFrame
      Group    Size  Time
0  Moderate  Medium     1
1  Moderate   Small     1
2     Short   Small     2
3      Tall   Large     1

Option 3:

dfg = df.groupby(by=["Group", "Size"], as_index=False).size()

# which results in a pandas.core.frame.DataFrame
      Group    Size  Time
0  Moderate  Medium     1
1  Moderate   Small     1
2     Short   Small     2
3      Tall   Large     1
Encumbrance answered 22/10, 2015 at 0:44 Comment(0)
R
97

Update after pandas 1.1 value_counts now accept multiple columns

df.value_counts(["Group", "Size"])

You can also try pd.crosstab()

Group           Size

Short          Small
Short          Small
Moderate       Medium
Moderate       Small
Tall           Large

pd.crosstab(df.Group,df.Size)


Size      Large  Medium  Small
Group                         
Moderate      0       1      1
Short         0       0      2
Tall          1       0      0

EDIT: In order to get your out put

pd.crosstab(df.Group,df.Size).replace(0,np.nan).\
     stack().reset_index().rename(columns={0:'Time'})
Out[591]: 
      Group    Size  Time
0  Moderate  Medium   1.0
1  Moderate   Small   1.0
2     Short   Small   2.0
3      Tall   Large   1.0
Rhachis answered 5/5, 2017 at 21:39 Comment(3)
nice. you can even add margins=True to get the marginal counts!Hearsh
Also df.value_counts(["Group", "Size"]).reset_index() will turn it into a dataframeDanieu
As you count all columns, you can use df.value_counts().Betsybetta
S
5

Other posibbility is using .pivot_table() and aggfunc='size'

df_solution = df.pivot_table(index=['Group','Size'], aggfunc='size')
Sisyphus answered 6/8, 2020 at 17:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.