【问题标题】:Enumerate each row for each group in a DataFrame枚举 DataFrame 中每个组的每一行
【发布时间】:2013-06-18 04:05:04
【问题描述】:

在 pandas 中,如何添加一个新列来根据给定的分组枚举行?

例如,假设以下 DataFrame:

import pandas as pd
import numpy as np

a_list = ['A', 'B', 'C', 'A', 'A', 'C', 'B', 'B', 'A', 'C']
df = pd.DataFrame({'col_a': a_list, 'col_b': range(10)})
df
  col_a  col_b
0     A      0
1     B      1
2     C      2
3     A      3
4     A      4
5     C      5
6     B      6
7     B      7
8     A      8
9     C      9

我想添加一个col_c,它根据col_a 的分组和col_b 的排序为我提供“组”的第N 行。

期望的输出:

  col_a  col_b  col_c
0     A      0      1
3     A      3      2
4     A      4      3
8     A      8      4
1     B      1      1
6     B      6      2
7     B      7      3
2     C      2      1
5     C      5      2
9     C      9      3

我很难找到col_c。您可以使用 .sort_index(by=['col_a', 'col_b']) 进行正确的分组和排序,现在只需访问该新列并标记每一行。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    cumcount,正是这种情况:

    df['col_c'] = g.cumcount()
    

    正如文档中所说:

    将每个组中的每个项目编号从 0 到该组的长度 - 1。


    原始答案(在定义 cumcount 之前)。

    您可以创建一个辅助函数来执行此操作:

    def add_col_c(x):
        x['col_c'] = np.arange(len(x))
        return x
    

    首先按 col_a 列排序:

    In [11]: df.sort('col_a', inplace=True)
    

    然后将此函数应用于每个组:

    In [12]: g = df.groupby('col_a', as_index=False)
    
    In [13]: g.apply(add_col_c)
    Out[13]:
      col_a  col_b  col_c
    3     A      3      0
    8     A      8      1
    0     A      0      2
    4     A      4      3
    6     B      6      0
    1     B      1      1
    7     B      7      2
    9     C      9      0
    2     C      2      1
    5     C      5      2
    

    为了得到1,2,...,你可以使用np.arange(1, len(x) + 1)

    【讨论】:

    • 这基本上回答了这个问题——尽管 gjreda 要求枚举 col_a 并按 col_b 排序。
    • 太棒了,谢谢@AndyHayden。知道这将是一个 groupby,但无法弄清楚如何正确应用它。
    【解决方案2】:

    给定的答案都涉及为每个组调用一个 python 函数,如果你有很多组,矢量化方法应该更快(我没有检查过)。

    这是我纯粹的 numpy 建议:

    In [5]: df.sort(['col_a', 'col_b'], inplace=True, ascending=(False, False))
    In [6]: sizes = df.groupby('col_a', sort=False).size().values
    In [7]: df['col_c'] = np.arange(sizes.sum()) - np.repeat(sizes.cumsum() - sizes, sizes)
    In [8]: print df
      col_a  col_b  col_c
    9     C      9      0
    5     C      5      1
    2     C      2      2
    7     B      7      0
    6     B      6      1
    1     B      1      2
    8     A      8      0
    4     A      4      1
    3     A      3      2
    0     A      0      3
    

    【讨论】:

      【解决方案3】:

      您可以定义自己的函数来处理它:

      In [58]: def func(x):
         ....:     x['col_c'] = x['col_a'].argsort() + 1 
         ....:     return x
         ....: 
      
      In [59]: df.groupby('col_a').apply(func)
      Out[59]: 
        col_a  col_b  col_c
      0     A      0      1   
      3     A      3      2   
      4     A      4      3   
      8     A      8      4   
      1     B      1      1   
      6     B      6      2   
      7     B      7      3   
      2     C      2      1   
      5     C      5      2   
      9     C      9      3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-03
        • 2020-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-26
        • 1970-01-01
        • 2020-02-11
        相关资源
        最近更新 更多