• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SettingWithCopyWarningA value is trying to be set on a copy of a slice from a DataFramePandas库

武飞扬头像
方如一
帮助1

1 SettingWithCopyWarning

SettingWithCopyWarning仅仅是一个警告 Warning,而不是错误 Error。一般情况下它是不会影响程序的运行的,但是知道如何避免SettingWithCopyWarning是很有必要的。

2 Pandas操作返回类型

Pandas中的一些操作会返回原数据,另一些操作会返回数据的副本(Copy)。

比如说我们要提取额下面DataFrame里面第一行和第二行的数据,A.loc[0:1,'A':'B']。数据有两种返回方式,一是左边的df2直接选中df1中的部分数据,二是右边的df2不对原数据df1进行修改,独立返回了一个copy。

学新通

当我们再次要对返回的内容操作,比如说要把第1行第B列的数据改成5时,A.loc[0:1,'A':'B']['B'][1]=5,这时计算机不知道到底是修改左边的df2呢还是右边的df2。

学新通 

 3 链式索引

SettingWithCopyWarning提示的后面还有让我们去看一个文件,里面的大致意思是引起警告的原因是我们使用了链式索引。链式索引是指连续使用多个索引操作,例如A[A.b==2]['c']。

  1.  
    import pandas as pd
  2.  
    A=pd.DataFrame({'a':[1,2,3],'b':[2,2,4],'c':[2,2,5]})
  3.  
    print(A)
  4.  
    #OutA: a b c
  5.  
    # 0 1 2 2
  6.  
    # 1 2 2 2
  7.  
    # 2 3 4 5
  8.  
    print(A[A.b==2])
  9.  
    #Out: a b c
  10.  
    # 0 1 2 2
  11.  
    # 1 2 2 2
  12.  
    A[A.b==2]['c']=5
  13.  
    #<string>:1: SettingWithCopyWarning:
  14.  
    #A value is trying to be set on a copy of a slice from a DataFrame.
  1.  
    print(A)
  2.  
    #OutA:a b c
  3.  
    # 0 1 2 2
  4.  
    # 1 2 2 2
  5.  
    # 2 3 4 5
  6.  
    #再次查看A,发现A确实没有修改

这次警告是因为A[A.b==2]['c']是链式索引,简单的说该命令直接使用了两次方括号索引。

第一次索引先执行A[A.b==2],返回了一个DataFrame(不知道是会返回原数据A,还是返回A的副本B);第二次索引['c']=5是找到上一步得到的DataFrame的c列对该列赋值。

但是计算机很困惑,第一步的确生成了一个DataFrame,但是第二次修改到底是修改原数据A还是A的副本B?

从再次查看A可知第二次的赋值并没有修改原始的A,只是对A的副本B进行赋值。这种情况对应的解决方案很简单:使用loc或者iloc函数将两次链式操作简化为一步操作,确保第一次索引返回的是A。如下可以看出A被修改了

  1.  
    A.loc[A.b==2,'c']=4
  2.  
    print(A)
  3.  
    #Out: a b c
  4.  
    # 0 1 2 4
  5.  
    # 1 2 2 4
  6.  
    # 2 3 4 5

除了两次方括号索引这样明显的链式索引,还有比较隐蔽的链式索引

  1.  
    import pandas as pd
  2.  
    A=pd.DataFrame({'class':[1,2,3],'name':[2,2,4],'grade':[2,2,5]})
  3.  
    print(A)
  4.  
    #Out: class name grade
  5.  
    # 0 1 2 2
  6.  
    # 1 2 2 2
  7.  
    # 2 3 4 5
  8.  
    B=A.loc[A.name==A.grade]
  9.  
    print(B)
  10.  
    #Out: class name grade
  11.  
    # 0 1 2 2
  12.  
    # 1 2 2 2
  13.  
    B.loc[0,'class']=2
  14.  
    print(B)
  15.  
    #SettingWithCopyWarning:A value is trying to be set on a copy of a slice from a
  16.  
    #Out: class name grade
  17.  
    # 0 1 2 2
  18.  
    # 1 2 2 2
学新通

这次使用了loc函数,依然出现了警告。因为虽然把链式索引分成了两个代码,但是B变量它依然可能是原始数据A的副本,也可能是原始数据A。这意味着当我们尝试修改B时,可能也修改了A。这种情况下的警告解决方案是:创建新数据B时明确告知 Pandas 创建一个副本.copy():

  1.  
    import pandas as pd
  2.  
    A=pd.DataFrame({'class':[1,2,3],'name':[2,2,4],'grade':[2,2,5]})
  3.  
    print(A)
  4.  
    B=A.loc[A.name==A.grade].copy()
  5.  
    B.loc[0,'class']=2
  6.  
    print(B)
  7.  
    #Out:class name grade
  8.  
    # 0 2 2 2
  9.  
    # 1 2 2 2

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfaaca
系列文章
更多 icon
同类精品
更多 icon
继续加载