【问题标题】:Add a sequential counter column on groups to a pandas dataframe将组上的顺序计数器列添加到熊猫数据框
【发布时间】:2023-02-03 15:47:15
【问题描述】:

我觉得有比这更好的方法:

import pandas as pd
df = pd.DataFrame(
    columns="   index    c1    c2    v1 ".split(),
    data= [
            [       0,  "A",  "X",    3, ],
            [       1,  "A",  "X",    5, ],
            [       2,  "A",  "Y",    7, ],
            [       3,  "A",  "Y",    1, ],
            [       4,  "B",  "X",    3, ],
            [       5,  "B",  "X",    1, ],
            [       6,  "B",  "X",    3, ],
            [       7,  "B",  "Y",    1, ],
            [       8,  "C",  "X",    7, ],
            [       9,  "C",  "Y",    4, ],
            [      10,  "C",  "Y",    1, ],
            [      11,  "C",  "Y",    6, ],]).set_index("index", drop=True)
def callback(x):
    x['seq'] = range(1, x.shape[0] + 1)
    return x
df = df.groupby(['c1', 'c2']).apply(callback)
print df

为达到这个:

   c1 c2  v1  seq
0   A  X   3    1
1   A  X   5    2
2   A  Y   7    1
3   A  Y   1    2
4   B  X   3    1
5   B  X   1    2
6   B  X   3    3
7   B  Y   1    1
8   C  X   7    1
9   C  Y   4    1
10  C  Y   1    2
11  C  Y   6    3

有没有办法避免回调?

【问题讨论】:

    标签: python pandas dataframe group-by running-count


    【解决方案1】:

    使用cumcount(),查看文档here

    In [4]: df.groupby(['c1', 'c2']).cumcount()
    Out[4]: 
    0     0
    1     1
    2     0
    3     1
    4     0
    5     1
    6     2
    7     0
    8     0
    9     0
    10    1
    11    2
    dtype: int64
    

    如果你想从 1 开始排序

    In [5]: df.groupby(['c1', 'c2']).cumcount()+1
    Out[5]: 
    0     1
    1     2
    2     1
    3     2
    4     1
    5     2
    6     3
    7     1
    8     1
    9     1
    10    2
    11    3
    dtype: int64
    

    【讨论】:

      【解决方案2】:

      这可能有用

      df = df.sort_values(['userID', 'date'])
      grp = df.groupby('userID')['ItemID'].aggregate(lambda x: '->'.join(tuple(x))).reset_index()
      print(grp)
      

      它将创建这样的序列

      【讨论】:

        【解决方案3】:

        如果你有一个类似于下面的数据框,并且你想通过从 c1c2 构建它来添加 seq 列,即在其他列中保持类似值的运行计数(或直到出现标志) (s),继续阅读。

        df = pd.DataFrame(
            columns="  c1      c2    seq".split(),
            data= [
                    [ "A",      1,    1 ],
                    [ "A1",     0,    2 ],
                    [ "A11",    0,    3 ],
                    [ "A111",   0,    4 ],
                    [ "B",      1,    1 ],
                    [ "B1",     0,    2 ],
                    [ "B111",   0,    3 ],
                    [ "C",      1,    1 ],
                    [ "C11",    0,    2 ] ])
        

        然后首先找到组启动器,(下面使用str.contains()(和eq()),但可以使用任何创建布尔系列的方法,例如lt()ne()isna()等)并调用@987654330 @ 在其上创建一个系列,其中每个组都有唯一的标识值。然后将它用作 groupby().cumsum() 操作中的石斑鱼。

        总之,使用类似于下面的代码。

        # build a grouper Series for similar values
        groups = df['c1'].str.contains("A$|B$|C$").cumsum()
        
        # or build a grouper Series from flags (1s)
        groups = df['c2'].eq(1).cumsum()
        
        # groupby using the above grouper
        df['seq'] = df.groupby(groups).cumcount().add(1)
        

        【讨论】:

          【解决方案4】:

          Jeff's answer 的整洁度很好,但我更喜欢明确排序......虽然通常不会为这些类型的用例覆盖我的 df(例如 Shaina Raza's answer)。

          因此,要在每个 ('c1', 'c2') 组中创建一个按 'v1' 排序的新列:

          df["seq"] = df.sort_values(by=['c1','c2','v1']).groupby(['c1','c2']).cumcount()
          

          你可以检查:

          df.sort_values(by=['c1','c2','seq'])
          

          或者,如果你想覆盖 df,那么:

          df = df.sort_values(by=['c1','c2','seq']).reset_index()
          

          【讨论】:

            猜你喜欢
            • 2022-09-18
            • 2017-08-21
            • 1970-01-01
            • 2012-09-04
            • 2016-09-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多