Pandas新增列触发SettingWithCopyWarning的解决方法及原因
嘿,这个警告我熟!咱们先搞懂为啥会出现它,再一步步解决~
原因分析
- 这个警告的核心问题是:
dfabovemax不是一个独立的DataFrame,而是从另一个大DataFrame切片得到的「副本」。pandas没法确定你是想修改这个副本,还是想间接修改原始的大DataFrame,所以抛出警告提醒你可能操作不符合预期。 - 举个例子,如果你之前是通过类似
dfabovemax = original_df[original_df['value'] > max_val]这种方式得到的dfabovemax,那它本质上是原始DataFrame的切片副本,不是视图,直接给它加列就会触发这个警告。
解决方法
给你三个实用的方案,按需选择:
方案1:提前显式创建副本(最推荐)
在生成dfabovemax的时候,直接加上.copy(),明确告诉pandas这是一个独立的副本,后续操作就不会有警告了:
# 假设你之前是这样得到dfabovemax的,现在加上.copy() dfabovemax = original_df[original_df['some_condition']].copy() # 然后再执行你的计算和赋值操作 import datetime fmt = '%Y-%m-%d' ytodt2 = [] for i in dfabovemax.index: s='2005-{}'.format(i) dt = datetime.datetime.strptime(s, fmt) tt = dt.timetuple() ytodt2.append(tt.tm_yday) dfabovemax['YtoDt'] = ytodt2
方案2:用.loc明确指定赋值范围
如果不想提前复制,那赋值的时候用.loc[:, 'YtoDt']来明确操作当前DataFrame的所有行和新列,消除pandas的不确定性:
# 其他代码不变,最后赋值改成下面这样 dfabovemax.loc[:, 'YtoDt'] = ytodt2
方案3:优化计算逻辑,抛弃循环(更高效)
其实你计算年内天数的循环可以用pandas的内置方法替代,既简洁又高效,还能避免循环的冗余:
import pandas as pd # 把索引转成2005年的datetime类型 dfabovemax.index = pd.to_datetime('2005-' + dfabovemax.index.astype(str)) # 直接提取年内天数 dfabovemax['YtoDt'] = dfabovemax.index.dayofyear
这样一行就能搞定循环的工作,而且性能比循环好很多,尤其是数据量大的时候。
内容的提问来源于stack exchange,提问作者Rajeeva I
相关产品推荐
相关产品推荐

