由“浅拷贝”导致的SettingWithCopyWarning和解决方法(隐性链式索引Chain assignment问题)

import pandas as pd
import numpy as np

Header=['ALPHA','CL','CD','Cm','CK','CY']
RawData=pd.DataFrame({'sp1L':[0,0,0],
                      'sp2L':[-10,-10,-10],
                      'ALPHA':[-6,-5.75,-5.5],
                      'CL':[-0.10452846326765346,-0.10018806161207627,-0.09584575252022398],
                      'CD':[0.0024787521766663585,0.003182780796509667,0.004086771438464067],
                      'Cm':[36,33.0625,30.25]
})

temp=RawData.loc[0:1,:]
for h in Header:
    if (h == temp.columns).any():
        continue
    else:
        temp.loc[:,h]=np.nan

问题描述

以上代码在运行时会在最后一句temp.loc[:,h]=np.nan处报SettingWithCopyWarning,无论如何修改赋值方式都无法去除。

后来发现这是一个隐性的链式索引(chain indexing)语句。
链式索引问题的官方描述

Outside of simple cases, it’s very hard to predict whether it will return a view or a copy (it depends on the memory layout of the array, about which pandas makes no guarantees)

真正导致警告的原因在上面一句:
temp=RawData.loc[0:1,:]

这是一个浅拷贝语句,实际没有将RawData的一个切片复制到一段新的内存中保存,而是仅仅为原切片创建了一个“别名”temp。因此,后续语句在继续对temp进行引用时:
temp.loc[:,h]

相当于
RawData.loc[0:1,:][:,h]

链式索引方法
关于链式索引的风险可参考上面的官方解释。
简单说,就是链式索引方式会使得python解释器使用__getitem__(),这样会导致返回值不确定是指定切片的一个copy还是仅为切片指定了一个别名
如果不想改原数据时,它返回了一个别名,那所有的修改就会直接改在原数据上;反过来,如果想修改原数据,但它返回的是一个copy,更改就无法生效。
具体返回的是什么跟待处理数据的具体格式、大小和pandas对待处理数据的内存规划有关,这些都是不确定的,所以尽量避免使用链式索引。

解决方法

temp=RawData.loc[0:1,:]改为深拷贝方法:

import copy # 代码头部加入引用copy库
temp=copy.deepcopy(RawData.loc[IndexPosition,:])

其余部分不变,运行后SettingWithCopyWarning消失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值