1. 原因分析
SettingWithCopyWarning报警是链式操作的不确定性导致的,详见 https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy。
链式操作是依序执行的,即先执行步骤一,再在中间结果的基础上执行步骤二,依次类推。前驱步骤的执行结果不一定符合后继步骤的输入条件,导致链式操作中间环节不一定成功。
链式操作包括链式筛选和链式赋值两种:
- 链式筛选:例如
df['one']['second']
,先执行df['one']
,再执行df['second']
; - 链式赋值:例如
df[condition]['wen_cha'] = df['bWendu'] - df['yWendu']
,先执行df[condition]
,再执行df['wen_cha'] = df['bWendu'] - df['yWendu']
。
在链式赋值中,先筛选出子DataFrame,再对子DataFrame进行赋值,由于无法自动判断筛选出的子DataFrame是对象的引用还是拷贝,所以赋值能否成功未知。
2. 处理思路
- 避免任何形式的链式赋值;
- 将链式操作转换成一次操作;
- 赋值操作仅在原对象上进行,并且一步到位;
- 需要链式筛选时,使用
df.loc[:, ('one', 'second')]
替代df['one']['second']
; - 需要对象拷贝时,使用
df.copy()
。
3. 解决方案
- 方案一:使用
df.loc
一次性完成筛选和赋值; - 方案二:使用
df.copy()
显式拷贝筛选结果,再进行赋值。