按类型分组填充NA值时DataFrame未更新的技术求助
我刚碰到过一模一样的问题!你的代码逻辑思路是对的,但踩了pandas里一个经典的「视图vs副本」的坑,导致原DataFrame根本没被更新。
问题根源
问题出在链式索引返回的是副本而非视图:当你写wines.loc[wines.type == t, c].fillna(...)时,这是两次索引操作的链式调用——先筛选出对应类型的行,再取出指定列。这种情况下pandas无法确定返回的是原数据的视图还是临时副本,默认会返回副本。所以你用inplace=True只是修改了这个临时副本,原wines DataFrame完全没变化。
两种靠谱的解决方法
方法1:用单一loc索引直接赋值(最直观)
避免链式索引,用一次loc精准定位到要修改的行和列,直接把填充后的值赋值回去:
wines = pd.read_csv('winequalityN.csv') #数据导入 na_list = wines.isna().sum() cols_na = na_list[na_list != 0] #存在NA值的列 means = wines.groupby('type').mean() #按类型(红或白)分组计算各列均值 # 按红、白类型分别用对应均值填充NA值 for t in ['red','white']: for c in cols_na.keys(): # 先创建筛选掩码,再用单一loc定位赋值 type_mask = wines['type'] == t wines.loc[type_mask, c] = wines.loc[type_mask, c].fillna(means.loc[t, c])
这种写法明确操作原DataFrame的对应位置,不会有视图/副本的混淆。
方法2:用transform简化代码(更高效)
其实完全可以不用手动循环,用groupby+transform的组合,一行代码搞定按组填充,还更高效:
wines = pd.read_csv('winequalityN.csv') na_list = wines.isna().sum() cols_na = na_list[na_list != 0].keys() # 按type分组,对有NA的列用组内均值填充 wines[cols_na] = wines.groupby('type')[cols_na].transform( lambda x: x.fillna(x.mean()) )
这种方式利用pandas的向量化操作,比循环更简洁,大数据量下性能也更好。
验证修复效果
修改后可以运行下面的代码确认所有NA值都被填充了:
print(wines.isna().sum()) # 输出里所有列的NA计数都应该是0
内容的提问来源于stack exchange,提问作者TuchmanMarsh




