【python | pandas】关于pandas处理的copy和view理解与报错处理


在写代码时遇到如下问题:

一、发现问题

df=A                  #此处A是一个DataFrame
df=df[~df['客户号'].isnull()]    
df.loc[:,'客户名称']=df['客户名称'].fillna('未命名')

获得如下warning信息D:\Anaconda3\lib\site-packages\pandas\core\indexing.py:1675: 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 instead

发现df已经按自己的想法修改了,没有问题,那为什么这里会报warning呢?


二、查阅资料

  1. 查阅官方文档
    pandas: Returning a view versus a copy
  2. slice与index获得相应的copy和view结构:
    pandas处理是copy还是view

Pandas中不同的查询语句会得到不同的结果,分别是copy和view,他们两者主要的区别在于:

  1. view直接与原表相连,对view的修改会产生对原表进行修改
  2. copy产生一个副本,对浅层拷贝(shallow copy)的操作与原表仍然有关,对深层拷贝(deep copy)的操作与原表无关

三、分析问题

我们知道,对于DataFrame的查询,本质上会调用其__getitem__这个“分离事件”(separate event)

  1. 对列索引[]的操作

使用[['a','b']]时,像这样调用:df.__getitem__('a').__getitem__('b',value),官方的说法是:

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)

即:除了简单的情况之外,很难预测它是返回视图还是副本(这取决于数组的内存布局,pandas 对此不做任何保证)

在我的环境中,直接通过列来进行单列slice得到的结果是一个view;进行多列slice时得到的结果是一个shallow copy;对boolean处理得到的结果是一个shallow copy:

在这里插入图片描述

  1. 对.loc的操作

而使用.loc(:,('a','b')),会这样调用:df.loc.__setitem__((slice(None), ('a','b')), value)
根据官网的意思是:

You may be wondering whether we should be concerned about the loc property in the first example. But dfmi.loc is guaranteed to be dfmi itself with modified indexing behavior, so dfmi.loc.getitem / dfmi.loc.setitem operate on dfmi directly. Of course, dfmi.loc.getitem(idx) may be a view or a copy of dfmi.

即:.loc.getitem(idx)可能是view或copy;但无论是copy或者是view,.loc保证其本身具有修改的索引行为。

在我的环境中,对单列进行.loc操作,得到的结果是view,多列是shallow copy
在这里插入图片描述

  1. 那是不是用loc和用[]是一样的?

我的理解是:在当前版本(pandas版本1.4.0)这两种方法对多列产生的都是shallow copy,都可以对原表产生修改,但还是按官方建议来写,用.loc对列进行修改,以免出现数据嵌套的问题。

在这里插入图片描述

(对于视图,应该是等价的,但对于copy,地址是不一样的)


四、解决问题

回到主题,看起来

df=df[~df['客户号'].isnull()]    
df.loc[:,'客户名称']=df['客户名称'].fillna('未命名')

这两句都是按loc合理的写入的,为什么会有warning,问题并不出在这里,而是在上面一句:

df=A

在这里插入图片描述

在这里,df和A是等价的,意味着df和A指向的应该是同一个东西,对于df进行操作的时候,实际上A的值也修改了。
针对此,pandas给出了warning,我们只要对A产生一个deep copy,再赋值给A就可以使得对df的操作不影响到A了,如下

在这里插入图片描述
报错消失


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值