如何按id_vector分组计算众数并新增列至原Pandas DataFrame?
Pandas按分组计算众数并生成新列的解决方案
问题场景
给定如下Pandas DataFrame:
import pandas as pd df = pd.DataFrame({ 'id_vector': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E'], 'svm_prediction': [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0] })
需要新增一列new_label,规则为:
- 每个值对应其所在
id_vector分组中svm_prediction的众数:众数为1则填1,为0则填0 - 若0和1出现频率相等,则填2
预期结果如下:
result = pd.DataFrame({ 'id_vector': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E'], 'svm_prediction': [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0], 'new_label': [0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2] })
用户尝试两种方法均失败:
- 方法一:调用
groupby对象的mode()报错,提示无此属性df.groupby('id_vector')['svm_prediction'].mode() - 方法二:直接对整列求众数赋值,结果除第一行外全为NaN
df['average'] = df[['svm_prediction']].mode(axis=0)
可行解决方案
方案一:统计分组计数后映射标签
import pandas as pd df = pd.DataFrame({ 'id_vector': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E'], 'svm_prediction': [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0] }) # 统计每个分组中0和1的出现次数 counts = df.groupby('id_vector')['svm_prediction'].value_counts().unstack(fill_value=0) # 根据计数生成对应标签 counts['new_label'] = counts.apply( lambda x: 0 if x[0] > x[1] else 1 if x[1] > x[0] else 2, axis=1 ) # 将标签映射回原DataFrame df['new_label'] = df['id_vector'].map(counts['new_label']) print(df)
方案二:用transform直接广播分组计算结果
import pandas as pd df = pd.DataFrame({ 'id_vector': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E'], 'svm_prediction': [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0] }) def get_mode_label(series): count_0 = (series == 0).sum() count_1 = (series == 1).sum() return 0 if count_0 > count_1 else 1 if count_1 > count_0 else 2 # 用transform将分组计算结果广播到每一行 df['new_label'] = df.groupby('id_vector')['svm_prediction'].transform(get_mode_label) print(df)
说明
- 方案一先统计每组0、1的计数,再根据计数规则生成标签,最后通过
map将标签赋值给原DataFrame的对应行 - 方案二自定义函数计算每组的标签,利用
transform直接将分组结果广播到原DataFrame的每一行,代码更简洁直观
内容的提问来源于stack exchange,提问作者Al_Mt
相关产品推荐
相关产品推荐

