在运行以下Python代码时,Pandas抛出SettingWithCopyWarning警告:

row_data = df_pred.loc[key]
row_data['col'] = new_value

df_pred是一个数据框,根据索引从数据框中获取一行,然后对该行的一个字段进行赋值,警告的详细内容如下:

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

该警告的意思是:在DataFrame的一个切片上的copy上进行赋值操作。出现警告是因为该赋值操作可能不会影响到原始的数据框。

从代码上来理解:row_data 是原始数据框的一个切片(df_loc[key]),该切片可能是原始数据框的一个视图(View),也可能是原始数据框的一个副本(Copy)。如果row_data是原始数据框的一个视图,对row_data进行数据修改不会影响到df_pred。建议使用df_pred.loc[row_indx,col_index] 方式,该方式肯定修改原始数据框。

一,深拷贝和浅拷贝

在使用DataFrame修改数据时,要知道深拷贝和浅拷贝的区别。图例描述了浅拷贝和深拷贝的区别,假设B复制了A,当修改B时,如果A也跟着变了,说明这是浅拷贝;如果A没变,那就是深拷贝。

也就是说,浅拷贝是创建了对象的一个引用,而深拷贝是创建了对象的一个独立的实体。

二,数据的视图和副本

在pandas中,浅拷贝也称作数据的视图(View),深拷贝也称作数据的副本(Copy),Pandas 中的某些操作可以返回数据的视图(View),而某些其他操作将返回数据的副本(Copy)。

SettingWithCopyWarning 警告暗示:赋值操作可能没有按照预期执行,你应该检查结果以确保结果没有出错。

如果你的代码执行的结果符合预期,那么你可以忽略警告,但这并不是良好的编码实践,SettingWithCopyWarning 警告不应该被忽略。在采取下一步行动之前,花点时间了解以下为什么Pandas会抛出这一警告。

三,警告出现的原因

直接抛出结论,警告出现的原因只有一个:

出现警告的原因是链式赋值

当 Pandas 检测到链式赋值(Chained assignment)时会生成警告,链式赋值是指通过使用链式索引来赋值。链式索引(Chaining)是指连续使用多个索引,例如data[1:5][1:3]。

使用链式索引赋值的两种方式:

  • 第一种是显式的,索引是连续的,例如,data.iloc[1][3] = value
  • 第二种是隐式的,例如,先定义 df = data.iloc[1],再使用 df[3] = value 也属于链式赋值

链式赋值可以在一行中进行,也可以跨越多行,只要Pandas检测到链式赋值,Python就会抛出SettingWithCopyWarning警告。

1,显式的链式赋值

举个例子,使用链式索引对bidder列进行赋值:

data[data.bidder == 'parakeet2004']['bidderrate'] = 100

生成警告是因为我们把两个索引操作链接在一起,代码中直接使用了两次中括号,所以这种格式比较容易理解。但如果我们使用其他访问方法,例如 .bidderrate.loc[].iloc[].ix[],也是如此,我们的链式操作一个接一个独立执行:

data[data.bidder == 'parakeet2004']
['bidderrate'] = 100

第一次是访问操作(get),返回一个 DataFrame,其包含所有 bidder 等于 'parakeet2004' 的行。第二个是赋值操作(set),是在这个新的 DataFrame 上运行的,我们压根没有在原始 DataFrame 上运行。

这个解决方案很简单:使用 loc 将链式操作组合到一个操作中,以便 Pandas 可以确保 set 操作是在原始 DataFrame上执行。Pandas 会始终确保下面这样的非链式 set 操作起作用。

data.loc[data.bidder == 'parakeet2004', 'bidderrate'] = 100

2,隐式的链式赋值

举个例子,使用原始数据框的一个变量,对变量赋值,这是隐式的链式赋值:

winners = data.loc[data.bid == data.price]
winners.loc[304, 'bidder'] = 'therealname'

隐式的链式索引可能跨越多行代码发生,也可能在一行代码内发生。因为 winners 是作为 get 操作的输出创建的(data.loc[data.bid == data.price]),它可能是原始 DataFrame 的副本,也可能不是,但除非我们检查,否则我们不能确认。当我们对 winners 进行索引时,我们实际上使用的是链式索引。这意味着当我们尝试修改 winners 时,我们可能也修改了 data

在实际的代码中,这些行可能会跨越很大的距离,因此追踪问题可能会更困难,但情况是与示例类似的。

为了防止这种情况下的警告,解决方案是在创建新 DataFrame 时明确告知 Pandas 这是创建的一个副本,对副本的修改不会影响到原始对象:

winners = data.loc[data.bid == data.price].copy()
winners.loc[304, 'bidder'] = 'therealname'

敲门就是,学会识别链式索引,不惜一切代价避免使用链式索引。如果要更改原始数据,请使用单一索引赋值操作。如果你想要一个副本,请确保显式调用copy()函数强制让 Pandas 创建副本。

提一个中肯的建议,即使SettingWithCopyWarning警告只在set 时才会发生,但在进行 get 操作时,最好也避免使用链式索引。不仅因为链式操作较慢,而且因为链式索引始终是一个潜在的问题,只要你稍后进行赋值操作,就可能不会影响到原始对象,这可能不是你的预期操作,所以,请不惜一切代价避免使用链式索引。

参考文档:

python学习笔记之Pandas 中 SettingwithCopyWarning 的原理和解决方案

SettingwithCopyWarning: How to Fix This Warning in Pandas

DataFrame 链式赋值的更多相关文章

  1. python学习(二十一) Python 中的链式赋值

    Python的链式赋值如下:

  2. pyhton链式赋值在可变类型/不可变类型上的区别以及其本质

    关于链式赋值的一些注意点: a=[]b=[]x=y=[]print(a==b) #Trueprint(x==y) #Trueprint(a is b) #Falseprint(x is y) #Tru ...

  3. Python特色的序列解包、链式赋值、链式比较

    一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...

  4. Python 笔试集(1):关于 Python 链式赋值的坑

    前言 Python 的链式赋值是一种简易型批量赋值语句,一行代码即可为多个变量同时进行赋值. 例如: x = y = z = 1 链式赋值是一种非常优雅的赋值方式,简单.高效且实用.但同时它也是一个危 ...

  5. 第4.7节 Python特色的序列解包、链式赋值、链式比较

    一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...

  6. Python链式赋值执行顺序及执行方式的证明

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在<关于Python链式赋值的赋值顺序问题& ...

  7. 关于Python链式赋值的赋值顺序问题

    在<第4.7节 Python特色的序列解包.链式赋值.链式比较>一文中,老猿这样介绍的: 链式赋值是用一行语句将多个变量赋值为同一个值,语法如下: 变量1=变量2=变量n=赋值表达式 该语 ...

  8. C++中的链式操作

    代码编译环境:Windows7 32bits+VS2012. 1.什么是链式操作 链式操作是利用运算符进行的连续运算(操作).它的特点是在一条语句中出现两个或者两个以上相同的操作符,如连续的赋值操作. ...

  9. 由反转链表想到python链式交换变量

    这两天在刷题,看到链表的反转,在翻解体思路时看到有位同学写出循环中一句搞定三个变量的交换时觉得挺6的,一般用的时候都是两个变量交换(a,b=b,a),这种三个变量的交换还真不敢随便用,而且这三个变量都 ...

随机推荐

  1. SSM整合案例--用户登录

    实现用户登录案例,并进行非法拦截 实现当用户未登录时,无法跳转到出登录页面以外的任何页面,拦截用户仍在登陆页面:当用户登录成功即可跳转到其他页面 (1)导入依赖 <!-- https://mvn ...

  2. Unity中动态创建Mesh

    什么是Mesh? Mesh是指的模型的网格,3D模型是由多边形拼接而成,而多边形实际上又是由多个三角形拼接而成的.即一个3D模型的表面其实是由多个彼此相连的三角面构成.三维空间中,构成这些三角形的点和 ...

  3. 数据分析之路 第一篇 numpy

    第一篇 numpy 1.N维数组对象 :ndarray在Python中既然有了列表类型,为啥还要整个数组对象(类型)?那是因为:1.数组对象可以除去元素间运算所需要的循环,使得一维向量更像单个数据2. ...

  4. ASP.NET Core 1.0: Deploy to IIS

    尽管ASP.NET最新的官方文档记录了如何Deploy to IIS,但是实际操作起来依旧磕磕绊绊.官方文档地址:https://docs.asp.net/en/latest/publishing/i ...

  5. suseoj 1207: 大整数的乘法(java, 大数相乘, C/C++, 大数相乘)

    1207: 大整数的乘法 时间限制: 1 Sec  内存限制: 128 MB提交: 7  解决: 2[提交][状态][讨论版][命题人:liyuansong] 题目描述 求两个不超过200位的非负整数 ...

  6. Test Complete 的自动化测试 --- 计算器

    Test Complete 的自动化测试 --- 计算器   ·PS:工具:Test Complete, OS: win XP, (win10 不支持该工具的自动化测试) ·该篇博客将会讲1.如何录制 ...

  7. python学习基础—day01

    一. python是什么? 优势:简单, 可以跨平台 劣势:执行效率没有C语言那么高 python是解释型语言,逐行编译解释,在不同的系统windows与Linux,需要不同的解释器来编译. 而编译型 ...

  8. 简单说说基于JWT的token认证方式

    一.什么是认证 好多人不知道什么是认证,认证,其实就是服务端确认用户身份.Http协议是无状态的,客户端发送一条请求,服务端返回一条响应,二者就算做成一单买卖,一拍两散.在很久以前,互联网所能提供的服 ...

  9. Future模式的学习以及JDK内置Future模式的源码分析

    并发程序设计之Future模式 一).使用Future模式的原因 当某一段程序提交了一个请求,期待得到一个答复,但服务程序对这个请求的处理可能很慢,在单线程的环境中,调用函数是同步的,必须等到服务程序 ...

  10. vue在移动端实现复制数值到剪贴版

    实现按键就指定内容复制到设备的剪贴版,这里是复制快递单号 html <div slot="footer" v-if="express.number" st ...