繁体   English   中英

在组上添加顺序计数器列到 pandas dataframe

[英]Add a sequential counter column on groups to a pandas dataframe

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

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

有没有办法避免回调?

使用cumcount()<\/code> ,请参阅此处<\/a>的文档

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

这可能有用

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

完整的工作代码

import pandas as pd
df = pd.DataFrame(
    [['A', 'X', 3], ['A', 'X', 5], ['A', 'Y', 7], ['A', 'Y', 1],
     ['B', 'X', 3], ['B', 'X', 1], ['B', 'X', 3], ['B', 'Y', 1],
     ['C', 'X', 7], ['C', 'Y', 4], ['C', 'Y', 1], ['C', 'Y', 6]],
    columns=['c1', 'c2', 'v1'])

df['seq'] = df.groupby(['c1', 'c2']).cumcount() + 1
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

如果您有一个类似于下面的 dataframe 并且您想通过从c1构建它来添加seq列,请继续阅读。

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

然后首先找到组起始者( str.contains()在下面使用,但也可以使用eq()lt()ne()等)并在其上调用cumsum()以创建一个系列,其中每个组都有一个唯一的识别价值。 然后将其用作groupby().cumsum()操作的分组器。

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

# build a grouper Series
groups = df['c1'].str.contains("A$|B$|C$").cumsum()
# groupby using the above grouper
df['seq'] = df.groupby(groups).cumcount().add(1)

Jeff 的回答简洁明了,但我更喜欢明确排序……尽管通常不会为这些类型的用例覆盖我的 df(例如Shaina Raza 的回答)。

因此,要在每个 ('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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM