g = df.groupby('class')
g.apply(lambda x: x.sample(g.size().min()).reset_index(drop=True))
class val
0 c1 1
1 c1 1
2 c2 2
3 c2 2
4 c3 3
5 c3 3
Answers to your follow-up questions
- The
xin thelambdaends up being a dataframe that is the subset ofdfrepresented by the group. Each of these dataframes, one for each group, gets passed through thislambda. gis thegroupbyobject. I placed it in a named variable because I planned on using it twice.df.groupby('class').size()is an alternative way to dodf['class'].value_counts()but since I was going togroupbyanyway, I might as well reuse the samegroupby, use asizeto get the value counts… saves time.- Those numbers are the the index values from
dfthat go with the sampling. I addedreset_index(drop=True)to get rid of it.