为何Pandas DataFrame指定条件下的值修改未生效?
Pandas布尔索引赋值后原DataFrame未更新的原因及解决方法
首先创建目标DataFrame:
import pandas as pd import numpy as np a = pd.DataFrame({ "one":[np.NAN,np.NAN,"e"], "two":["a","s","d"], "three":[1,2,2] })
对应的初始表格:
| one | two | three | |
|---|---|---|---|
| 0 | NaN | a | 1 |
| 1 | NaN | s | 2 |
| 2 | e | d | 2 |
需要修改满足以下条件的one列值:
one列为空值(null)three列等于1
你先用布尔索引筛选出目标行:
a[(a["one"].isnull()) & (a["three"]==1)]
得到结果:
| one | two | three | |
|---|---|---|---|
| 0 | NaN | a | 1 |
接着执行赋值代码后,原DataFrame却没有变化:
a[(a["one"].isnull()) & (a["three"]==1)].loc[a["one"]!=a["one"], "one"] = "replaced"
原因分析
这是因为你用了链式索引:a[...].loc[...]这种连续索引的方式,会返回原DataFrame的临时副本,而不是直接指向原数据的视图。当你给这个副本赋值时,修改的只是临时对象,原DataFrame完全不受影响。如果开启了Pandas的警告,你会看到SettingWithCopyWarning,提示你可能在修改副本而非原数据。
另外,a["one"]!=a["one"]本质和a["one"].isnull()效果一致,但在这里属于多余操作,还进一步强化了对副本的操作。
正确解决方法
直接操作原DataFrame,避免链式索引即可:
方法1:单一loc索引赋值
把所有条件整合到loc里,直接定位目标位置修改:
a.loc[(a["one"].isnull()) & (a["three"] == 1), "one"] = "replaced"
方法2:使用mask函数
通过mask对满足条件的位置进行替换:
a["one"] = a["one"].mask((a["one"].isnull()) & (a["three"] == 1), "replaced")
执行后原DataFrame会更新为:
| one | two | three | |
|---|---|---|---|
| 0 | replaced | a | 1 |
| 1 | NaN | s | 2 |
| 2 | e | d | 2 |
内容的提问来源于stack exchange,提问作者신동혁
相关产品推荐
相关产品推荐

