如何用另一列的众数填充Pandas DataFrame中某列的缺失值
用分组众数填充缺失值的解决方案
嘿,我懂你遇到的问题了——用transform("mode")直接填充的时候总是失败,这是因为mode()方法返回的结果格式和我们需要的不太匹配,咱们一步步来搞定它!
先回顾你的数据集
首先,先确认下咱们的初始数据:
import pandas as pd import numpy as np raw_data = { 'first_name': ['Jake', 'Jake', 'Tina', 'Jake', 'Amy'], 'last_name': ['Miller', 'Smith', 'Ali', 'Milner', 'Cooze'], 'age': [42, np.nan, 36, 24, 73], 'sex': ['m', np.nan, 'f', 'm', 'f'], 'preTestScore': [4, np.nan, np.nan, 2, 3], 'postTestScore': [25, np.nan, np.nan, 62, 70] } df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'age', 'sex', 'preTestScore', 'postTestScore'])
核心问题:用first_name分组的sex众数填充缺失值
你之前的代码失败,是因为groupby().transform("mode")返回的是带有多级索引的Series/DataFrame,而不是每个分组对应的单个标量值。比如Jake的分组里sex的众数是'm',但mode()返回的是一个包含这个值的小Series,直接填充会出现维度不匹配的问题。
解决方法是用一个lambda函数,提取每个分组众数的第一个值(如果有多个众数,我们默认取第一个):
# 用first_name分组后的sex众数填充缺失值 df["sex"] = df["sex"].fillna( df.groupby("first_name")["sex"].transform(lambda x: x.mode().iloc[0]) )
运行这段代码后,那个Jake对应的缺失sex就会被正确填充为'm',完全符合你的预期。
进阶:先尝试分组众数,无则用其他列/全局众数填充
你的最终目标是先尝试用分组众数填充,若某个分组里没有可用的众数(比如该分组的sex全是缺失值),再用其他逻辑(比如全局众数、其他分组的众数)填充。咱们可以分两步实现:
步骤1:先用first_name分组众数填充
这里我们加个判断,确保如果分组里没有众数(全是缺失),就返回np.nan,留到下一步处理:
df["sex"] = df["sex"].fillna( df.groupby("first_name")["sex"].transform( lambda x: x.mode().iloc[0] if not x.mode().empty else np.nan ) )
步骤2:用全局/其他分组的众数填充剩余缺失值
如果还有没填充的缺失值,我们可以用全局的sex众数来补:
# 获取全局sex的众数 global_sex_mode = df["sex"].mode().iloc[0] # 填充剩余缺失值 df["sex"] = df["sex"].fillna(global_sex_mode)
如果你想换成用last_name分组的众数填充剩余缺失值,也可以这么写:
df["sex"] = df["sex"].fillna( df.groupby("last_name")["sex"].transform( lambda x: x.mode().iloc[0] if not x.mode().empty else np.nan ) )
这样就完美实现了“优先分组众数,次选其他逻辑”的填充策略啦!
内容的提问来源于stack exchange,提问作者d84_n1nj4
相关产品推荐
相关产品推荐

