【问题标题】:Get group id back into pandas dataframe将组 ID 返回到 pandas 数据帧
【发布时间】:2013-02-10 22:20:00
【问题描述】:

对于数据框

In [2]: df = pd.DataFrame({'Name': ['foo', 'bar'] * 3,
   ...:                    'Rank': np.random.randint(0,3,6),
   ...:                    'Val': np.random.rand(6)})
   ...: df
Out[2]: 
  Name  Rank       Val
0  foo     0  0.299397
1  bar     0  0.909228
2  foo     0  0.517700
3  bar     0  0.929863
4  foo     1  0.209324
5  bar     2  0.381515

我有兴趣按名称和排名进行分组,并可能获取汇总值

In [3]: group = df.groupby(['Name', 'Rank'])
In [4]: agg = group.agg(sum)
In [5]: agg
Out[5]: 
                Val
Name Rank          
bar  0     1.839091
     2     0.381515
foo  0     0.817097
     1     0.209324

但我想在原始 df 中获取一个字段,其中包含该行的组号,例如

In [13]: df['Group_id'] = [2, 0, 2, 0, 3, 1]
In [14]: df
Out[14]: 
  Name  Rank       Val  Group_id
0  foo     0  0.299397         2
1  bar     0  0.909228         0
2  foo     0  0.517700         2
3  bar     0  0.929863         0
4  foo     1  0.209324         3
5  bar     2  0.381515         1

在 pandas 中有没有好的方法来做到这一点?

我可以用python得到它,

In [16]: from itertools import count
In [17]: c = count()
In [22]: group.transform(lambda x: c.next())
Out[22]: 
   Val
0    2
1    0
2    2
3    0
4    3
5    1

但它在大型数据帧上相当慢,所以我认为可能有更好的内置 pandas 方式来做到这一点。

【问题讨论】:

    标签: python pandas group-by


    【解决方案1】:

    使用来自 pandas 0.20.2+ 的 GroupBy.ngroup

    df["GroupId"] = df.groupby(["Name", "Rank"]).ngroup()
    print (df)
      Name  Rank       Val  GroupId
    0  foo     2  0.451724        4
    1  bar     0  0.944676        0
    2  foo     0  0.822390        2
    3  bar     2  0.063603        1
    4  foo     1  0.938892        3
    5  bar     2  0.332454        1
    

    【讨论】:

      【解决方案2】:

      正确的解决方法是使用grouper.label_info

      df["GroupId"] = df.groupby(["Name", "Rank"]).grouper.label_info
      

      它会自动将df 数据框中的每一行与相应的组标签相关联。

      【讨论】:

      • 这之前有效,但 label_info 似乎已在 pandas 1.0 中删除
      【解决方案3】:

      DataFrameGroupBy.grouper 对象中存储了很多方便的东西。例如:

      >>> df = pd.DataFrame({'Name': ['foo', 'bar'] * 3,
                         'Rank': np.random.randint(0,3,6),
                         'Val': np.random.rand(6)})
      >>> grouped = df.groupby(["Name", "Rank"])
      >>> grouped.grouper.
      grouped.grouper.agg_series        grouped.grouper.indices
      grouped.grouper.aggregate         grouped.grouper.labels
      grouped.grouper.apply             grouped.grouper.levels
      grouped.grouper.axis              grouped.grouper.names
      grouped.grouper.compressed        grouped.grouper.ngroups
      grouped.grouper.get_group_levels  grouped.grouper.nkeys
      grouped.grouper.get_iterator      grouped.grouper.result_index
      grouped.grouper.group_info        grouped.grouper.shape
      grouped.grouper.group_keys        grouped.grouper.size
      grouped.grouper.groupings         grouped.grouper.sort
      grouped.grouper.groups            
      

      等等:

      >>> df["GroupId"] = df.groupby(["Name", "Rank"]).grouper.group_info[0]
      >>> df
        Name  Rank       Val  GroupId
      0  foo     0  0.302482        2
      1  bar     0  0.375193        0
      2  foo     2  0.965763        4
      3  bar     2  0.166417        1
      4  foo     1  0.495124        3
      5  bar     2  0.728776        1
      

      grouper.group_info[0] 可能有一个更好的别名潜伏在某个地方,但无论如何这应该可以工作。

      【讨论】:

      • 另一个别名好像是grouped.grouper.labels[0]
      • 唯一的问题是石斑鱼没有记录,不保证它不会破裂。
      • 三年后,这件事仍然没有记录。但是很容易发现df.grouperBaseGrouper 类。 group_info 方法在代码中定义为 here,您可以进一步追溯以确认以下内容:1) group_info[1] 是唯一组标识符的数组,2) 行 @ 的组标识符987654332@是group_info[0][i],3)group_info[3]是组数
      • 也许这是我对 python 的天真,但我很惊讶没有一个简单的、记录在案的方法。我提出这个问题是因为我想使用sklearn.cross_validation.StratifiedShuffleSplit 并在几个不同列的独特组合中进行分层。这个组 ID 正是我完成这项工作所需的单列,但很难找到。我很想知道这是否是对熊猫的滥用。
      • @jflournoy:巧合的是,我现在有一个 PR,可以通过规范的方式访问这些信息。
      猜你喜欢
      • 2019-08-07
      • 2018-08-16
      • 2021-04-22
      • 1970-01-01
      • 2019-09-23
      • 2023-04-10
      • 2021-10-11
      • 2018-03-03
      • 1970-01-01
      相关资源
      最近更新 更多