You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

按类型分组填充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

火山引擎 最新活动