zoukankan      html  css  js  c++  java
  • Pandas

    转自:https://blog.csdn.net/qq_42711381/article/details/90451301

    由于刚好也遇到这个问题,记录下来

    使用的DataFrame的

    image

    当使用 frame2['year']['two'] = 10000, 即df名[列名][行名]的方式去赋值就会报错, 提示如下

    SettingWithCopyWarning:
    A value is trying to be set on a copy of a slice from a DataFrame

    See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

    进入提示网页, 查找与SettingWithCopyWarning有关部分, 这里简单翻译了一下(渣翻译, 推荐大家去看原文, 在最后几部分里)

    chained indexing
    
    这就是出现警告的原因, 我们在使用pandas中要极力避免出现chained index)

    下面是一个例子解释到底什么是chained indexing

    In [4]: dfmi = pd.DataFrame([list('abcd'), list('efgh'), list('ijkl'), list('mnop')],
           ...:                     columns=pd.MultiIndex.from_product([['one', 'two'], ['first', 'second']]))
           ...:
        
        In [5]: dfmi
        Out[5]:
            one          two
          first second first second
        0     a      b     c      d
        1     e      f     g      h
        2     i      j     k      l
        3     m      n     o      p

    我们通过两种不同的方式去访问同一值

    #第一种方式
            In [6]: dfmi['one']['second']
        Out[6]:
        0    b
        1    f
        2    j
        3    n
        Name: second, dtype: object
        
    #第二种方式
        In [7]: dfmi.loc[:,('one', 'second')]
        Out[7]:
        0    b
        1    f
        2    j
        3    n
        Name: (one, second), dtype: object

    可以看出虽然访问方式不同, 但是返回的结果是相同的. 相同结果, 但其实第二种访问方式应该是我们所推荐使用的, 原因如下

    第一种访问方式

    使用dfmi['one']['second']其实是分为两个独立事件完成的, 一个事情接着一件事情发生:

    第一步 执行dfmi['one']

    第二步 在第一步的基础上执行dfmi_with_one['second'], 相当于在第一步返回Series基础上, 检索索引['second']

    看似是一步到位的访问, 其实在内部调用了两次__getitem__

    第二种方式访问

    fmi.loc[:,('one', 'second')] 相当于将一个嵌套的元组(slice(None), ('one', 'second'))传递给一个__getitem__, 这就使得pandas将其作为一个整体来处理, 第二种方式比第一种方式速度更快

    这里的第一种访问方式就是chained indexing, 接下来解决为什么chained indexing会造成警告.

           #第二种访问方式(推荐方式)
           dfmi.loc[:, ('one', 'second')] = value
            #其实在编译器中是这样操作的
            dfmi.iloc.setitem((slice(None), ('one', 'second')), value)
            
            #但是这一段代码编译器处理就很不同了
            
             #第一种访问方式chained indexing
            dfmi['one']['second'] = value
            #其实在编译器中是这样操作的
            dfmi.__getitem__('one').__setitem__('second', value)

    问题的关键就出在这里的__getitem__上, 因为我们很难预测到这里的__getitem__返回的是一个视图或是一个copy, 因为我们无法确定__setitem))修改的到底是真实的dfmi或是暂时的copy副本, 这就是SettingWithCopy想要警告我们的.

    到此问题就算是解决了, 出现警告的原因在于无法预测到底修改的是视图还是副本.

    注意

    dfmi.loc保证是dfmi本身伴随修改索引行为(这句话有点不太通顺, 大家可以去看看原文, 重点是后面一句), 所以dfmi.loc.__getitem__和dfmi.loc__setitem__方法一定是直接作用在dfmi上的. 当然dfmi.loc.__getitem__(idx)就无法预测到时作用在视图上或是副本上了.

    另一种会出现这种警告的情形, 虽然这里并没有明显的链式索引.

    In [9]: def do_something(df):
           ...:     foo = df[['bar', 'baz']]
           ...:     #对于foo是视图或是副本, 其实我们是无法得知的
           ...:     foo['quux'] = value
           ...:     return foo

    解决警告的方案:

    使用 DafaFrameming.loc[行名, 列名] = 值 的方式去赋值, 而不是使用DataFrame[][]的形式去赋值.

  • 相关阅读:
    HDU 2041--超级楼梯(递推求解)
    HDOJ2037 今年暑假不AC (经典的贪心问题)
    JavaWeb---总结(十)HttpServletRequest对象(一)
    JavaWeb---总结(十一)使用Cookie进行会话管理
    JavaWeb---总结(十二)Session
    JavaWeb---总结(十三)使用Session防止表单重复提交
    JavaWeb---总结(十四)JSP原理
    JavaWeb---总结(十五)JSP基础语法
    JavaWeb---总结(十六)JSP指令
    JavaWeb---总结(十七)JSP中的九个内置对象
  • 原文地址:https://www.cnblogs.com/luhouxiang/p/12306822.html
Copyright © 2011-2022 走看看