代码之家  ›  专栏  ›  技术社区  ›  jpp

带就地填充的索引[重复]

  •  1
  • jpp  · 技术社区  · 7 年前

    这两者的区别是什么:

    熊猫 df.loc[:,('col_a','col_b')]

    和

    df.loc[:,['col_a','col_b']]

    下面的链接没有提到后者,尽管它是有效的。两人都有观点吗?第一个拉取视图,第二个拉取副本吗?喜欢学习熊猫。

    http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

    谢谢

    0 回复  |  直到 11 年前
        1
  •  31
  •   unutbu    11 年前

    如果DataFrame有一个简单的列索引,那么就没有区别了。 例如

    In [8]: df = pd.DataFrame(np.arange(12).reshape(4,3), columns=list('ABC'))
    
    In [9]: df.loc[:, ['A','B']]
    Out[9]: 
       A   B
    0  0   1
    1  3   4
    2  6   7
    3  9  10
    
    In [10]: df.loc[:, ('A','B')]
    Out[10]: 
       A   B
    0  0   1
    1  3   4
    2  6   7
    3  9  10
    

    但如果数据帧具有多索引,则可能会有很大的不同:

    df = pd.DataFrame(np.random.randint(10, size=(5,4)),
                      columns=pd.MultiIndex.from_arrays([['foo']*2+['bar']*2,
                                                         list('ABAB')]),
                      index=pd.MultiIndex.from_arrays([['baz']*2+['qux']*3,
                                                       list('CDCDC')]))
    
    #       foo    bar   
    #         A  B   A  B
    # baz C   7  9   9  9
    #     D   7  5   5  4
    # qux C   5  0   5  1
    #     D   1  7   7  4
    #     C   6  4   3  5
    
    In [27]: df.loc[:, ('foo','B')]
    Out[27]: 
    baz  C    9
         D    5
    qux  C    0
         D    7
         C    4
    Name: (foo, B), dtype: int64
    
    In [28]: df.loc[:, ['foo','B']]
    KeyError: 'MultiIndex Slicing requires the index to be fully lexsorted tuple len (1), lexsort depth (0)'
    

    关键错误是,必须对多索引进行排序。如果我们这样做,我们仍然会得到不同的结果:

    In [29]: df.sortlevel(axis=1).loc[:, ('foo','B')]
    Out[29]: 
    baz  C    9
         D    5
    qux  C    0
         D    7
         C    4
    Name: (foo, B), dtype: int64
    
    In [30]: df.sortlevel(axis=1).loc[:, ['foo','B']]
    Out[30]: 
          foo   
            A  B
    baz C   7  9
        D   7  5
    qux C   5  0
        D   1  7
        C   6  4
    

    为什么? df.sortlevel(axis=1).loc[:, ('foo','B')] 选择第一列级别等于的列 foo ,第二列级别为 B .

    相反 df.sortlevel(axis=1).loc[:, ['foo','B']] 选择第一列级别为 福 或 B .关于第一列级别,没有 B 列,但有两个 福 柱。

    df.loc[...] 像 一 表示 ,你应该假设 df.loc 可能正在返回副本或视图。熊猫文件没有规定任何你应该遵守的规则。 然而,如果你 分配 形式

    df.loc[...] = value
    

    然后你可以相信熊猫会改变 df 它本身

    文档之所以警告要区分视图和副本,是为了让您知道使用表单的链指定的陷阱

    df.loc[...][...] = value
    

    这里,熊猫 df。loc[…] 首先,它可能是视图或副本。如果是副本,那么

    df。loc[…][...] = 价值
    

    正在修改 df ,因此对 df 它本身雪上加霜的是,对副本的影响也会丢失,因为没有对副本的引用,因此在赋值语句完成后无法访问副本,因此(至少在CPython中)副本很快就会被垃圾收集。


    我不知道有什么实用的防傻子方法 先验的 确定是否 df。loc[…] 将返回视图或副本。

    然而,有一些经验法则可能有助于指导你的直觉(但请注意,我们在这里讨论的是实现细节,因此不能保证熊猫将来需要这样做):

    • 如果生成的NDFrame不能表示为 基本的NumPy数组,那么它可能是一个副本。因此,选择任意行或列将导致复制。选择连续行和/或连续列(可以表示为切片)可能会返回视图。
    • 如果生成的NDFrame具有不同数据类型的列,则 df。loc 可能会再次返回一份副本。

    然而,有一种简单的方法可以确定 x = df.loc[..] 这是一种观点 后天的 :只需查看是否在 x df .如果是,那就是一种观点,如果不是, 十、 这是一份副本。