【问题标题】:How to access pandas groupby dataframe by key如何按键访问pandas groupby数据框
【发布时间】:2013-01-21 23:22:06
【问题描述】:

如何通过key访问groupby对象中对应的groupby数据框?

使用以下 groupby:

rand = np.random.RandomState(1)
df = pd.DataFrame({'A': ['foo', 'bar'] * 3,
                   'B': rand.randn(6),
                   'C': rand.randint(0, 20, 6)})
gb = df.groupby(['A'])

我可以遍历它以获取键和组:

In [11]: for k, gp in gb:
             print 'key=' + str(k)
             print gp
key=bar
     A         B   C
1  bar -0.611756  18
3  bar -1.072969  10
5  bar -2.301539  18
key=foo
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14

我希望能够通过其密钥访问组:

In [12]: gb['foo']
Out[12]:  
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14

但是当我尝试使用 gb[('foo',)] 执行此操作时,我得到了这个奇怪的 pandas.core.groupby.DataFrameGroupBy 对象,它似乎没有任何与我想要的 DataFrame 对应的方法。

我能想到的最好的是:

In [13]: def gb_df_key(gb, key, orig_df):
             ix = gb.indices[key]
             return orig_df.ix[ix]

         gb_df_key(gb, 'foo', df)
Out[13]:
     A         B   C
0  foo  1.624345   5
2  foo -0.528172  11
4  foo  0.865408  14  

但这有点讨厌,考虑到熊猫通常在这些事情上是多么的好。
这样做的内置方法是什么?

【问题讨论】:

    标签: python pandas dataframe group-by pandas-groupby


    【解决方案1】:

    你可以使用get_group方法:

    In [21]: gb.get_group('foo')
    Out[21]: 
         A         B   C
    0  foo  1.624345   5
    2  foo -0.528172  11
    4  foo  0.865408  14
    

    注意:这不需要为每个组创建中间字典/每个子数据帧的副本,因此比使用 dict(iter(gb)) 创建简单字典更节省内存。这是因为它使用了 groupby 对象中已有的数据结构。


    您可以使用 groupby 切片选择不同的列:

    In [22]: gb[["A", "B"]].get_group("foo")
    Out[22]:
         A         B
    0  foo  1.624345
    2  foo -0.528172
    4  foo  0.865408
    
    In [23]: gb["C"].get_group("foo")
    Out[23]:
    0     5
    2    11
    4    14
    Name: C, dtype: int64
    

    【讨论】:

      【解决方案2】:

      Python for Data Analysis 中的 Wes McKinney(pandas 的作者)提供了以下秘诀:

      groups = dict(list(gb))
      

      它返回一个字典,其键是您的组标签,其值是 DataFrame,即

      groups['foo']
      

      将产生您正在寻找的东西:

           A         B   C
      0  foo  1.624345   5
      2  foo -0.528172  11
      4  foo  0.865408  14
      

      【讨论】:

      • 谢谢,这很有用。如何修改代码以使groups = dict(list(gb)) 仅存储列C?假设我对其他列不感兴趣,因此不想存储它们。
      • 回答:dict(list( df.groupby(['A'])['C'] ))
      • 注意:使用dict(iter(g)) 更有效(但等效)。 (虽然get_group 是最好的方式/因为它不涉及创建字典/让你留在熊猫中!:D)
      • 我无法使用 groups(dict(list(gb)) 但您可以通过以下方式创建字典:gb_dict = {str(indx): str(val) for indx in gb.indx for val in gb.some_key} 然后通过 gb_dict[some_key] 检索值
      • 就用get_group(),这个食谱已经用了好几年了。
      【解决方案3】:

      而不是

      gb.get_group('foo')
      

      我更喜欢使用gb.groups

      df.loc[gb.groups['foo']]
      

      因为这样您也可以选择多个列。例如:

      df.loc[gb.groups['foo'],('A','B')]
      

      【讨论】:

      • 注意:您可以使用gb[["A", "B"]].get_group("foo")选择不同的列。
      【解决方案4】:
      gb = df.groupby(['A'])
      
      gb_groups = grouped_df.groups
      

      如果您正在寻找选择性 groupby 对象,请执行:gb_groups.keys(),并将所需的密钥输入以下 key_list..

      gb_groups.keys()
      
      key_list = [key1, key2, key3 and so on...]
      
      for key, values in gb_groups.items():
          if key in key_list:
              print(df.ix[values], "\n")
      

      【讨论】:

      • .iteritems() 适用于 Python 2(已死),因此我已为 Python 3 更改了此答案。
      【解决方案5】:

      我正在寻找一种方法来对 GroupBy obj 的一些成员进行抽样 - 必须解决发布的问题才能完成这项工作。

      根据some_key 列创建groupby 对象

      grouped = df.groupby('some_key')
      

      挑选 N 个数据帧并获取它们的索引

      sampled_df_i  = random.sample(grouped.indices, N)
      

      抓组

      df_list  = map(lambda df_i: grouped.get_group(df_i), sampled_df_i)
      

      可选 - 将其全部转回单个数据框对象

      sampled_df = pd.concat(df_list, axis=0, join='outer')
      

      【讨论】:

      • 这不起作用:sampled_df_i = random.sample(grouped.indicies, N)
      • @irene - 你能提供一个链接到更长的例子/更多的上下文吗?
      • 我收到以下错误:AttributeError: 'DataFrameGroupBy' object has no attribute 'indicies'
      猜你喜欢
      • 2018-12-09
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      • 2018-04-06
      • 2018-01-29
      相关资源
      最近更新 更多