【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了,如下

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


<think>嗯,用户遇到了两个Pandas的警告错误。首先是SettingWithCopyWarning,然后是RuntimeWarning关于转换中的无效值。我需要一步步分析可能的原因解决方法。 先看第一个警告,SettingWithCopyWarning。这通常是因为用户对一个DataFrame的切片副本进行修改,而Pandas不确定这个修改是否会影响原始数据。比如用户可能用了链式索引,比如df[df.A > 0]['B'] = 1,这样容易触发这个警告。这时候应该建议用户使用.loc来明确指定,比如df.loc[df.A > 0, 'B'] = 1,避免链式索引。 另外,如果用户确实需要修改副本,可能需要显式复制DataFrame,比如用.copy()方法创建副本,这样操作副本就不会影响原始数据,也能避免警告。或者使用pd.options.mode.chained_assignment设置来忽略这个警告,但最好还是解决根本问题。 然后是第二个RuntimeWarning,在类型转换时出现无效值,比如将非数字字符串转为数值时出错,比如字符串中有NaN或者无法转换的值。这时候需要检查数据中的异常值,可能用df.info()或df.describe()来查看数据类型统计信息,或者用df.isnull().sum()找缺失值。另外,转换时可以用errors参数,比如pd.to_numeric(df['col'], errors='coerce'),这样无效值会被转为NaN,避免报错。 用户可能需要结合这两个问题,先解决SettingWithCopyWarning,确保操作的是原始数据或正确副本,再处理数据类型转换的问题,清理或转换无效数据。可能需要用户提供相关代码片段,才能更具体地分析,但根据现有信息,给出这些建议应该有帮助。</think>这个报错主要包含两个问题,我为你分步解释并提供解决方案: 1️⃣ **`SettingWithCopyWarning` 警告分析** ```python pandas\core\indexing.py:1732: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame ``` 🔍 **根本原因**: - 当通过切片(slice)方式获取DataFrame的子集时(如 `df[condition]`),返回的可能是原数据的视图(view)或副本(copy) - 直接修改这个子集时,Pandas无法确定修改是否会影响到原始DataFrame 💡 **解决方案**: ```python # 错误示例(链式索引) df[df['A'] > 0]['B'] = 1 #
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值