如何基于Pandas DataFrame的GroupBy结果用众值填充/更新数据?
用分组众值填充Pandas DataFrame数据
需求描述
按key字段分组,获取每组value列的最频繁值(众值),并用该众值替换对应分组内所有的value值;若分组无有效众值(如所有value都是NaN),则保留NaN。
示例数据
import numpy as np import pandas as pd test_input = pd.DataFrame(columns=['key', 'value'], data=[[1, 'A'], [1, 'B'], [1, 'B'], [1, np.nan], [2, np.nan], [3, 'C'], [3, np.nan], [3, 'D'], [3, 'D']])
初始DataFrame:
key value 0 1 A 1 1 B 2 1 B 3 1 NaN 4 2 NaN 5 3 C 6 3 NaN 7 3 D 8 3 D
已实现的众值获取函数
现有按分组计算众值的函数:
def mode(df, key_cols, value_col, count_col): return (df.groupby(key_cols + [value_col]).size() .to_frame(count_col).reset_index() .sort_values(count_col, ascending=False) .drop_duplicates(subset=key_cols))
调用后得到各分组的众值结果:
freq_df = mode(test_input, ['key'], 'value', 'count')
输出的freq_df:
key value count 1 1 B 2 3 3 D 2
解决方案
方法1:合并数据后替换
通过merge匹配分组众值,再替换原字段:
# 合并原数据与众值结果,按key匹配 merged = test_input.merge(freq_df[['key', 'value']], on='key', suffixes=('_original', '_mode'), how='left') # 用众值替换原value,无众值时保留原内容 merged['value'] = merged['value_mode'].fillna(merged['value_original']) # 保留目标列 result = merged[['key', 'value']] print(result)
输出结果:
key value 0 1 B 1 1 B 2 1 B 3 1 B 4 2 NaN 5 3 D 6 3 D 7 3 D 8 3 D
方法2:映射字典快速替换(单分组键场景)
将众值结果转为字典,通过map直接替换:
# 构建key到众值的映射字典 mode_map = freq_df.set_index('key')['value'].to_dict() # 替换原value:存在映射则用众值,无映射保留原内容 test_input['value'] = test_input['key'].map(mode_map).fillna(test_input['value']) print(test_input)
此方法更简洁,仅适用于单分组键的场景,输出结果与方法1一致。
补充说明
- 两种方法都会自动处理无有效众值的分组(如key=2),保留原NaN;
- 若分组键为多个字段,优先使用方法1的合并方式。
内容的提问来源于stack exchange,提问作者Ailurophile
相关产品推荐
相关产品推荐

