【问题标题】:Pandas Multiindex and Groupby returns odd behaviorPandas Multiindex 和 Groupby 返回奇怪的行为
【发布时间】:2018-11-25 17:32:52
【问题描述】:

我已经使用 Pandas MultiIndex Dataframes 工作了几个星期,我感觉我并没有真正理解 GroupBy 对象背后的直觉,尤其是组的选择。

我们以这段代码为例:

import numpy as np
import pandas as pd

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]

tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

s = pd.Series(np.random.randn(8), index=index)
df = pd.DataFrame(np.random.randn(8, 4), index=arrays)

df.groupby(level=0).first()

最后一行的输出是这样的:

            0         1         2         3
bar  1.612350 -0.019424 -0.088925 -0.188864
baz  2.752485 -1.011006  0.249788  1.106547
foo  1.313016  0.716512  0.550851 -1.532394
qux  1.505173  0.758075  1.360808  1.261204

但是,在我看来,这种行为没有多大意义,因为它给了我第一组,就好像我会按第二级分组一样。我对上面代码的期望是这样的:

            0         1         2         3
one  1.612350 -0.019424 -0.088925 -0.188864
two  0.434829  1.698503 -0.213425  0.329733

到目前为止,我通过这样做实现了我想要的:

list(df.groupby(level=0))[0][1]

但是,这看起来并不意味着要这样做。

不知何故,我似乎对 GroupBy 对象有错误的期望。也许有人可以帮我解决我的困惑:)。

其他信息: 我不是在寻找特定的解决方案,如何获得“第一组”,因为我已经通过从对象中创建列表来获得它。我的问题是关于对 GroupBy 对象的理解以及它为什么选择第一个(或任何其他组)的方式。

【问题讨论】:

  • 我认为您的误解与first 方法的作用有关:它不选择第一个组,而是选择每个组中的第一个项目。
  • @user2285236 这正是我正在寻找的答案:)。但是,我不明白,为什么有一种方法可以获取每个组的第一个(或第 n 个)成员,而不是第 n 个组的方法。
  • 是的,pandas 只允许按键选择分组(如df.groupby(level=0).get_group('foo')) 这可能是因为默认情况下它不保留原始排序并按键排序。您的密钥已订购,因此您在list(df.groupby(level=0))[0][1] 看不到问题,但如果您的第一组是qux,您将再次获得barnth group 在这种情况下可能是模棱两可的,可能这就是他们只允许按键访问组的原因。
  • 非常感谢,现在一切都说得通了!

标签: python pandas dataframe indexing pandas-groupby


【解决方案1】:

由于@user2285236 在 cmets 中回答了我的问题,我尝试对其进行总结。

first() 方法不选择第一个组,而是选择每个组的第一个条目。没有像list(df.groupby(level=0))[0][1] 这样的内置实现的原因是groupby() 方法对条目进行排序。

例如,让我们安排上面的例子,让'第一'组'qux?。看起来像这样:

arrays = [['qux', 'qux', 'bar', 'bar', 'baz', 'baz', 'foo', 'foo'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]

tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

s = pd.Series(np.random.randn(8), index=index)
df = pd.DataFrame(np.random.randn(8, 4), index=arrays)

list(df.groupby(level=0))[0][1] 的调用返回:

                0         1         2         3
bar one -0.335708 -0.315253 -0.087970  0.754242
    two -1.608651  1.005786  1.800341 -1.059510 

而不是我期望的“第一”组:

                0         1         2         3
qux one -0.374186  0.812865  0.578298 -0.901881
    two -0.137799  0.278797 -1.171522  0.319980

但是,可以使用内置方法get_group() 调用每个组。因此,在这种情况下,我可以通过调用获得“第一”组:df.groupby(level=0).get_group('qux')

【讨论】:

    【解决方案2】:

    您可以给您的MultiIndex 级别名称,然后使用pd.DataFrame.query

    df.index.names = ['first', 'second']
    res = df.query('first == "bar"')
    
    print(res)
    
                         0         1         2         3
    first second                                        
    bar   one     0.555863 -0.080074 -1.726498 -0.874648
          two     1.099309  0.047887  0.294042  0.222972
    

    或者,使用pd.Index.get_level_values:

    res = df[df.index.get_level_values(0) == 'bar']
    

    【讨论】:

    • ilevel_0 无法访问任何名称 :-)
    • 哦,不错的提示!但我喜欢名字:)
    【解决方案3】:

    您是否在寻找多个索引切片?

    df.loc[pd.IndexSlice['bar',:],:]
    Out[319]: 
                    0        1         2         3
    bar one  0.807706  0.07296  0.638787  0.329646
        two -0.497104 -0.75407 -0.943406  0.484752
    

    【讨论】:

      【解决方案4】:

      您的第一列是 level_0,但您想按 level_1 分组。如果您重置索引,两列都将被分配一个列标题,您可以按此分组

      添加此代码:

      df=df.reset_index()
      
      df=df.groupby(['level_1']).first()
      df.head()
      

      【讨论】:

        猜你喜欢
        • 2018-10-28
        • 2017-11-15
        • 2019-09-29
        • 1970-01-01
        • 1970-01-01
        • 2017-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多