基于分组循环填充DataFrame中NaN值的技术求助
解决Pandas按优先级分组填充NaN值的问题
问题说明
给定如下DataFrame:
import pandas as pd df = pd.DataFrame({'segment': ['flowers', 'toys', 'gifts', 'gifts', 'toys', 'toys', 'flowers', 'flowers'], 'category': ['dandelion', 'car' , 'gift_1', 'gift_2', 'barby', 'gun', 'azalea','begonia'], 'discount 15%': [11, 8, 'NaN', 6, 6, 5, 9, 12], 'discount 20%': [15,'NaN', 15, 7, 9, 8, 'NaN', 14], 'discount 30%': [25, 10, 25, 9, 'NaN', 9, 13, 16], 'discount 40%': [35, 13, 'NaN', 15, 25, 11, 'NaN', 21]})
需求:仅对discount 15%至discount 40%列中的缺失值进行填充,规则如下:
- 优先按
category分组计算中位数填充 - 若该
category分组无有效值可计算中位数,则按segment分组的中位数填充 - 需在一次循环内完成
原代码的问题
你写的代码存在几个关键错误:
- 原数据中的
'NaN'是字符串,不是Pandas识别的np.nan,导致fillna无法处理缺失值 - 循环逻辑错误:
for i in col是遍历列名的每个字符,而非处理列中的缺失值 - 分两次循环,不符合一次循环的要求
- 检查缺失值的方式错误:
if i == 'Nan'大小写不对,且未使用Pandas的缺失值判断方法
正确解决方案
步骤1:转换缺失值类型
先将字符串'NaN'转换为Pandas可识别的np.nan,并将折扣列转为数值类型:
import pandas as pd import numpy as np # 定义折扣列范围 discount_cols = [col for col in df.columns if 'discount' in col] # 转换缺失值并转数值类型 df[discount_cols] = df[discount_cols].replace('NaN', np.nan).astype(float)
步骤2:一次循环完成两级填充
针对每个折扣列,先按category填充中位数,剩余未填充的NaN再用segment的中位数填充:
for col in discount_cols: # 第一优先级:按category分组填充中位数 df[col] = df[col].fillna(df.groupby('category')[col].transform('median')) # 第二优先级:填充剩余NaN(category分组无有效值的情况),用segment分组中位数 df[col] = df[col].fillna(df.groupby('segment')[col].transform('median'))
处理后结果示例
运行上述代码后,DataFrame的缺失值会按规则填充,部分结果如下:
segment category discount 15% discount 20% discount 30% discount 40% 0 flowers dandelion 11.0 15.0 25.0 35.0 1 toys car 8.0 8.333... 10.0 13.0 2 gifts gift_1 9.5 15.0 25.0 18.0 3 gifts gift_2 6.0 7.0 9.0 15.0
代码说明
transform('median')会为每个分组计算中位数,并映射回原DataFrame对应的行- 先执行category级填充,剩余的NaN说明该category分组内没有有效值(比如gift_1的discount 15%只有自己是NaN,分组中位数仍为NaN),此时再用segment的中位数填充
- 一次循环完成两级填充,符合需求
内容的提问来源于stack exchange,提问作者Pythondoesntlikeme
相关产品推荐
相关产品推荐

