使用pandas fillna()遇问题:按类别取众数填充缺失值无效
问题分析与修正
你的代码主要有两个问题导致缺失值没被填充,咱们一个个拆解:
1. 变量名拼写错误(最核心原因)
你循环里写了new_df= not_bonds.loc[mf["category"] == cat],这里的mf完全没定义啊!你的目标DataFrame名字是not_bonds,所以这里应该改成not_bonds["category"] == cat。这个错误会导致new_df是空的DataFrame,mode().tolist()得到的是空列表,自然不会进入填充逻辑分支,缺失值当然没变化。
2. 链式索引可能引发的视图/副本问题
即使变量名改对了,你用的not_bonds.loc[not_bonds['category'] == cat, 'fund_size'].fillna(..., inplace=True)属于链式索引(先通过loc取行,再单独取列),Pandas有时候会返回数据副本而非原数据的视图,这时inplace=True只会修改副本,不会影响原DataFrame。虽然你手动执行时有效,但循环上下文可能触发这个隐藏问题。
修正后的循环代码
把两个问题都解决后的代码如下:
for cat in not_bonds['category'].unique(): # 修正变量名错误,用not_bonds替代未定义的mf cat_mask = not_bonds['category'] == cat cat_fund_sizes = not_bonds.loc[cat_mask, 'fund_size'] mode_vals = cat_fund_sizes.mode().tolist() if mode_vals: # 直接判断列表是否非空,写法更简洁 # 避免链式索引,直接用loc赋值填充后的结果 not_bonds.loc[cat_mask, 'fund_size'] = cat_fund_sizes.fillna(mode_vals[0])
更高效的Pandas原生写法(推荐)
其实不用手动写循环,Pandas有更简洁的分组填充方案,利用groupby+transform就能实现:
# 定义一个返回系列众数(取第一个众数)的填充函数 def fill_mode(series): mode_val = series.mode().tolist() return series.fillna(mode_val[0] if mode_val else series) # 按category分组,对fund_size应用填充逻辑 not_bonds['fund_size'] = not_bonds.groupby('category')['fund_size'].transform(fill_mode)
这种写法不仅避免了循环的繁琐,还能利用Pandas的内置优化,运行效率更高,也不容易出错。
内容的提问来源于stack exchange,提问作者Satinder Pal Singh
相关产品推荐
相关产品推荐

