Pandas中groupby后用transform调用mode报错,如何解决?
问题:Pandas分组Transform计算众数报错解决
问题背景
给定如下数据集:
import pandas as pd thedf = pd.DataFrame({'id':['A','A','A','A','A','A','A','A', 'B','B','B','B','B','B','B','B'], 'group':['X','X','X','X','Y','Y','Y','Y', 'X','X','X','X','Y','Y','Y','Y'], 'value':['Ball','Coin','Coin','Coin','Yoyo','Yoyo','Toy','Puzzle', 'Ham','Grape','Ham','Ham','Pear','Pear','Pear','Ham']})
数据集预览:
| id | group | value | |
|---|---|---|---|
| 0 | A | X | Ball |
| 1 | A | X | Coin |
| 2 | A | X | Coin |
| 3 | A | X | Coin |
| 4 | A | Y | Yoyo |
| 5 | A | Y | Yoyo |
| 6 | A | Y | Toy |
| 7 | A | Y | Puzzle |
| 8 | B | X | Ham |
| 9 | B | X | Grape |
| 10 | B | X | Ham |
| 11 | B | X | Ham |
| 12 | B | Y | Pear |
| 13 | B | Y | Pear |
| 14 | B | Y | Pear |
| 15 | B | Y | Ham |
需要按id和group两级分组,用transform计算每组value列的众数,添加为mode列,期望结果:
| id | group | value | mode | |
|---|---|---|---|---|
| 0 | A | X | Ball | Coin |
| 1 | A | X | Coin | Coin |
| 2 | A | X | Coin | Coin |
| 3 | A | X | Coin | Coin |
| 4 | A | Y | Yoyo | Yoyo |
| 5 | A | Y | Yoyo | Yoyo |
| 6 | A | Y | Toy | Yoyo |
| 7 | A | Y | Puzzle | Yoyo |
| 8 | B | X | Ham | Ham |
| 9 | B | X | Grape | Ham |
| 10 | B | X | Ham | Ham |
| 11 | B | X | Ham | Ham |
| 12 | B | Y | Pear | Pear |
| 13 | B | Y | Pear | Pear |
| 14 | B | Y | Pear | Pear |
| 15 | B | Y | Ham | Pear |
尝试执行以下代码时报错:
thedf['mode'] = thedf.groupby(['id','group'])['value'].transform('mode')
错误信息:
ValueError: 'mode' is not a valid function name for transform(name)
原因分析
Pandas的transform方法支持的内置函数名称有限,mode不在内置列表中,因此直接传入字符串'mode'会触发报错,需要通过自定义逻辑来实现众数计算。
解决方法
方法1:自定义众数函数
编写函数返回分组的众数(若存在多个众数,取第一个):
def get_group_mode(series): return series.mode().iloc[0] thedf['mode'] = thedf.groupby(['id','group'])['value'].transform(get_group_mode)
方法2:使用匿名函数简化
直接在transform中调用mode方法并提取结果:
thedf['mode'] = thedf.groupby(['id','group'])['value'].transform(lambda x: x.mode().iloc[0])
方法3:借助Scipy工具(需安装Scipy)
如果已安装scipy,可以用其mode函数直接获取众数:
from scipy.stats import mode thedf['mode'] = thedf.groupby(['id','group'])['value'].transform(lambda x: mode(x, keepdims=False)[0])
以上三种方法均可生成符合预期的mode列。
内容的提问来源于stack exchange,提问作者Alexis
相关产品推荐
相关产品推荐

