使用.loc修改DataFrame值失败,触发SettingWithCopyWarning问题
问题情况
- 最初尝试用
.loc[row_indexer,col_indexer] = value修改DataFrame目标值失败,改用以下代码:
df.loc[df["subject"]!="subject1"]["Activity"] = np.nan
- 执行后触发
SettingWithCopyWarning警告:
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
"""Entry point for launching an IPython kernel.
- 检查数据后发现
Activity列的值完全没变化:
161280 0 161281 0 161282 0 161283 0 161284 0 .. 1215740 0 1215741 0 1215742 0 1215743 0 1215744 0 Name: Activity, Length: 1054465, dtype: int64
问题根源
你用的是链式索引:df.loc[...]["Activity"]。第一步df.loc[df["subject"]!="subject1"]返回的是原DataFrame的一个切片副本,后续对["Activity"]赋值只是修改了这个临时副本,根本没碰原DataFrame,所以原数据毫无变化,同时Pandas会抛出警告提示你这种操作的风险。
正确解决方案
把列索引直接放到.loc的第二个参数位置,一次性完成索引和赋值操作,直接修改原DataFrame:
df.loc[df["subject"] != "subject1", "Activity"] = np.nan
这样就能精准定位到符合条件的行和指定列,直接修改原数据,不会触发警告,也能达到你想要的效果。
内容的提问来源于stack exchange,提问作者Revolucion for Monica

