pandas警告SettingWithCopyWarning: A value is trying to ...原理和解决方案

Pandas的SettingWithCopyWarning警告常常困扰Python数据分析新手,该警告指出可能在尝试修改数据视图而非副本。本文深入探讨了警告产生的原因,包括链式赋值和隐蔽的链式操作,并提供了避免警告的解决方案,如使用loc或iloc,明确创建副本,以及了解视图与副本的区别。此外,还介绍了如何关闭警告以及理解这一警告在代码执行中的重要性。
摘要由CSDN通过智能技术生成

学习 Python 数据分析的同学总是遇到这个警告,查询中文资料,一般只能找到个别的解决办法,不一定适用于自己遇到的情况。查到的最常见解决办法就是直接设置为不显示警告。这实际上并不能解决问题,搜索资料发现这篇英文讲解 SettingWithCopyWarning 原理非常系统的文章,翻译了一下,分享给大家。

太长不看

  • 解决方案:学会识别链式索引,不惜一切代价避免使用链式索引
    注意:如果你看不懂这里的解决方案,请阅读此文前半部分,直到真正理解如何去做
    • 如果要更改原始数据,请使用单一赋值操作(loc):
    data.loc[data.bidder == 'parakeet2004', 'bidderrate'] = 100
    
    • 如果想要一个副本,请确保强制让 Pandas 创建副本:
    winners = data.loc[data.bid == data.price].copy() 
    winners.loc[304, 'bidder'] = 'therealname'
    
  • 强烈不推荐直接关闭警告,不过还是提供一下关闭警告的设置方法:
pd.set_option('mode.chained_assignment', None)
  • 深度解析底层代码和历史演变(可选阅读)

 

题图

SettingWithCopyWarning 是人们在学习 Pandas 时遇到的最常见的障碍之一。搜索引擎可以搜索到 Stack Overflow 上的问答、GitHub issues 和一些论坛帖子,分别提供了该警告在某些特定情况下的含义。会有这么多人同样遇到这个警告并不奇怪:有很多方法可以索引 Pandas 数据结构,每种数据结构都有各自的细微差别,甚至 Pandas 本身并不能保证两行代码的运行结果看起来完全相同。

本指南包含了生成警告的原因及解决方案,其中还包括一些底层细节,让你更好地了解代码内部的运行机制,最后提供了有关该话题的一些历史情况,解释代码底层以这样的方式运行的原因。

为了探索 SettingWithCopyWarning,我们将使用 eBay 3 天拍卖出售的 Xbox 的价格数据集,该数据集出自 Modelling Online Auctions 一书。先来了解下数据的基本结构:

 

import Pandas as pd

data = pd.read_csv('xbox-3-day-auctions.csv')
data.head()
  auctionid bid bidtime bidder bidderrate openbid price
0 8213034705 95.0 2.927373 jake7870 0 95.0 117.5
1 8213034705 115.0 2.943484 davidbresler2 1 95.0 117.5
2 8213034705 100.0 2.951285 gladimacowgirl 58 95.0 117.5
3 8213034705 117.5 2.998947 daysrus 10 95.0 117.5
4 8213060420 2.0 0.065266 donnie4814 5 1.0 120.0

如你所见,数据集的每一行都是某一次 eBay Xbox 出价信息。下面是对数据集中每列的简要说明:

  • auctionid - 每次拍卖的唯一标识符
  • bid - 本次拍卖出价
  • bidtime - 拍卖的时长,以天为单位,从投标开始累计
  • bidder - 投标人的 eBay 用户名
  • bidderrate - 投标人的 eBay 用户评级
  • openbid - 卖方为拍卖设定的开标价
  • price - 拍卖结束时的中标价

什么是 SettingWithCopyWarning?

首先要理解的是,SettingWithCopyWarning 是一个警告 Warning,而不是错误 Error。

错误表明某些内容是“坏掉”的,例如无效语法(invalid syntax)或尝试引用未定义的变量;警告的作用是提醒编程人员,他们的代码可能存在潜在的错误或问题,但是这些操作在该编程语言中依然合法。在这种情况下,警告很可能表明一个严重但不容易意识到的错误。

SettingWithCopyWarning 告诉你,你的操作可能没有按预期运行,需要检查结果以确保没有出错。

如果代码确实按预期工作,那么我们会很容易忽略该警告,但是 SettingWithCopyWarning 不应该被忽略。在进行下一步操作之前,我们需要花点时间了解这一警告显示的原因。

要了解 SettingWithCopyWarning,首先要知道,Pandas 中的某些操作会返回数据的视图(View),某些操作会返回数据的副本(Copy)。

View VS Copy

如上所示,左侧的视图 df2 只是原始数据 df1 一个子集,而右侧的副本创建了一个新的对象 df2

当我们尝试对数据集进行更改时,这可能会出现问题:

修改视图或副本

根据需求,我们可能想要修改原始 df1(左),也可能想要修改 df2(右)。警告让我们知道,代码可能并没有符合需求,修改到的可能并不是我们想要修改的那个数据集。

稍后会深入研究这个问题,但是现在先来了解一下,警告出现的两个主要原因以及对应的解决方案。

链式赋值(Chained Assignment)

当 Pandas 检测到链式赋值(Chained Assignment)时会生成警告。为了方便后续的解释,先来解释一些术语:

  • 赋值(Assignment) - 设置某些变量值的操作,例如 data = pd.read_csv('xbox-3-day-auctions.csv') ,有时会将这个操作称之为 设置(Set)
  • 访问(Access) - 返回某些值的操作,具体参照下方的索引和链式索引示例。有时会将这个操作称之为 获取(Get)
  • 索引(Indexing) - 任何引用数据子集的赋值或访问方法,例如 data[1:5]
  • 链式索引(Chaining) - 连续使用多个索引操作,例如data[1:5][1:3]

链式赋值是链式索引和赋值的组合。先快速浏览一下之前加载的数据集,稍后将详细介绍。在这个例子中,假设我们了解到用户 'parakeet2004'bidderrate 值不正确,需要修改这个 bidderrate 值,那么先来查看一下用户 'parakeet2004' 的当前值:

 

data[data.bidder == 'parakeet2004']
  auctionid bid bidtime bidder bidderrate openbid price
6 8213060420 3.00 0.186539 parakeet2004 5 1.0 120.0
7 8213060420 10.00 0.186690 parakeet2004 5 1.0 120.0
8 8213060420 24.99 0.187049 parakeet2004 5 1.0 120.0

有三行数据需要更新 bidderrate 字段,继续操作:

 

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

 

/Library/Frameworks/Python.framework/Versions/36/lib/python3.6/ipykernel/__main__.py:1:SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from aDataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation:http://Pandas.pydata.org/Pandas-docs/stable/indexinghtml#indexing-view-versus-copy
  if __name__ == '__main__':

神奇!我们“创造”出了 SettingWithCopyWarning

检查一下用户 'parakeet2004' 的相关值,可以看到值没有按预期改变:

 

data[data.bidder == 'parak
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值