How to groupby().transform() to value_counts() in pandas?
You could use groupby
+ transform
with value_counts
and idxmax
.
df['Most_Common_Price'] = (
df.groupby('Item')['Price'].transform(lambda x: x.value_counts().idxmax()))
df
Item Price Minimum Most_Common_Price
0 Coffee 1 1 2
1 Coffee 2 1 2
2 Coffee 2 1 2
3 Tea 3 3 4
4 Tea 4 3 4
5 Tea 4 3 4
An improvement involves the use of pd.Series.map
,
# Thanks, Vaishali!
df['Item'] = (df['Item'].map(df.groupby('Item')['Price']
.agg(lambda x: x.value_counts().idxmax()))
df
Item Price Minimum Most_Common_Price
0 Coffee 1 1 2
1 Coffee 2 1 2
2 Coffee 2 1 2
3 Tea 3 3 4
4 Tea 4 3 4
5 Tea 4 3 4
A nice way is to use pd.Series.mode
, if you want the most common element (i.e. the mode).
In [32]: df
Out[32]:
Item Price Minimum
0 Coffee 1 1
1 Coffee 2 1
2 Coffee 2 1
3 Tea 3 3
4 Tea 4 3
5 Tea 4 3
In [33]: df['Most_Common_Price'] = df.groupby(["Item"])['Price'].transform(pd.Series.mode)
In [34]: df
Out[34]:
Item Price Minimum Most_Common_Price
0 Coffee 1 1 2
1 Coffee 2 1 2
2 Coffee 2 1 2
3 Tea 3 3 4
4 Tea 4 3 4
5 Tea 4 3 4
As @Wen noted, pd.Series.mode
can returns a pd.Series
of values, so just grab the first:
Out[67]:
Item Price Minimum
0 Coffee 1 1
1 Coffee 2 1
2 Coffee 2 1
3 Tea 3 3
4 Tea 4 3
5 Tea 4 3
6 Tea 3 3
In [68]: df[df.Item =='Tea'].Price.mode()
Out[68]:
0 3
1 4
dtype: int64
In [69]: df['Most_Common_Price'] = df.groupby(["Item"])['Price'].transform(lambda S: S.mode()[0])
In [70]: df
Out[70]:
Item Price Minimum Most_Common_Price
0 Coffee 1 1 2
1 Coffee 2 1 2
2 Coffee 2 1 2
3 Tea 3 3 3
4 Tea 4 3 3
5 Tea 4 3 3
6 Tea 3 3 3