如何使用分组众数填充Pandas DataFrame中的缺失值:以玩具-颜色数据集为例
问题:如何按分组用每组最频繁的颜色填充Pandas DataFrame中的缺失值?
我有一个包含toy(玩具)和color(颜色)两列的pandas DataFrame,其中color列存在缺失值。我想按toy分组,使用每组中出现最频繁的color值填充该组对应的color缺失值。
示例数据集生成代码
import pandas as pd import numpy as np df = pd.DataFrame({ 'toy':['car'] * 4 + ['train'] * 5 + ['ball'] * 3 + ['truck'], 'color':['red', 'blue', 'blue', np.nan, 'green', np.nan, 'red', 'red', np.nan, 'blue', 'red', np.nan, 'green'] })
示例数据集
| toy | color | |
|---|---|---|
| 0 | car | red |
| 1 | car | blue |
| 2 | car | blue |
| 3 | car | NaN |
| 4 | train | green |
| 5 | train | NaN |
| 6 | train | red |
| 7 | train | red |
| 8 | train | NaN |
| 9 | ball | blue |
| 10 | ball | red |
| 11 | ball | NaN |
| 12 | truck | green |
期望结果
- car组的NaN替换为blue(blue是该组最频繁的颜色)
- train组的两个NaN替换为red(red是该组最频繁的颜色)
- ball组的NaN可以替换为blue或red(二者频次相同)
真实数据集说明
数据集中包含多种玩具类型(不止四种),且不存在所有color值均为缺失的玩具类型,无需处理这种极端情况。之前找过相关问题,但都没解决"用最频繁值填充缺失值"的需求。
回答
这里有两种简洁实用的方法可以实现你的需求,我会一步步解释清楚:
方法一:先算分组众数再映射填充
首先我们需要为每个玩具分组计算颜色的众数,考虑到可能存在多个众数(比如ball组的blue和red),我们可以取第一个众数作为填充值(完全符合你说的"选任意一个均可"的要求)。
# 计算每组color的众数,取第一个作为该组的填充基准值 toy_color_mode = df.groupby('toy')['color'].agg(lambda x: x.mode()[0]) # 把每个玩具对应的众数映射到原数据,并用它填充color列的缺失值 df['color'] = df['color'].fillna(df['toy'].map(toy_color_mode))
代码拆解
groupby('toy')['color'].agg(lambda x: x.mode()[0]):按玩具分组后,对每组的颜色列计算众数,x.mode()[0]确保我们取第一个出现的众数(即使有多个)。df['toy'].map(toy_color_mode):将每个玩具对应的众数匹配到原DataFrame的每一行位置。fillna():用匹配到的组内众数,精准填充对应组的颜色缺失值。
方法二:用transform一步到位填充
如果你想更简洁,transform方法可以直接将分组计算的结果广播回原DataFrame的对应行,省去单独映射的步骤:
df['color'] = df.groupby('toy')['color'].transform( lambda x: x.fillna(x.mode()[0]) )
代码拆解
groupby('toy')['color'].transform(...):对每个分组的颜色列执行填充操作,x.fillna(x.mode()[0])就是用当前组的众数填充组内的缺失值,transform会自动把处理后的结果对应回原数据的正确位置,一步完成分组计算+缺失值填充。
额外小技巧
如果你的需求是在多众数的情况下随机选一个填充,可以把lambda函数改成:
lambda x: x.fillna(x.mode().sample(1).iloc[0])
这样每次运行都会随机从组内众数里选一个来填充缺失值。
内容的提问来源于stack exchange,提问作者Kevin Markham
相关产品推荐
相关产品推荐

