列值将增加并重置另外两列中的更改

Aja*_*nni 4 python pandas pandas-groupby

我有数据框,我想继续增加值,直到val更改和id更改重置count值

data = [['p1',1],
        ['p1',1],
        ['p1',2],
        ['p2',3],
        ['p2',5],
        ['p3',1],
        ['p3',2],
        ['p3',1]]

df = pd.DataFrame(data = data,columns = ['id','val'])
Run Code Online (Sandbox Code Playgroud)

期望输出

       id val  count
    0  p1   1      1
    1  p1   1      1
    2  p1   2      2
    3  p2   3      1
    4  p2   5      2
    5  p3   1      1
    6  p3   2      2
    7  p3   1      3
Run Code Online (Sandbox Code Playgroud)

我已经到了这里

df['count'] = (df.val.diff() != 0).cumsum()
Run Code Online (Sandbox Code Playgroud)

这仅在val列更改时更改,但在id列更改时不会重置

ank*_*_91 7

你可以尝试groupby+transform用lambda

df['count'] = df.groupby("id")['val'].transform(lambda x: x.ne(x.shift()).cumsum())
Run Code Online (Sandbox Code Playgroud)
print(df)

   id  val  count
0  p1    1      1
1  p1    1      1
2  p1    2      2
3  p2    3      1
4  p2    5      2
5  p3    1      1
6  p3    2      2
7  p3    1      3
Run Code Online (Sandbox Code Playgroud)

  • 用shift变换就不错了~ (2认同)

ipj*_*ipj 6

基于您最初尝试的解决方案:

df['count'] = df.assign(dif = (df.val.diff() != 0)).groupby(['id']).dif.cumsum()
Run Code Online (Sandbox Code Playgroud)

结果:

   id  val  count
0  p1    1    1.0
1  p1    1    1.0
2  p1    2    2.0
3  p2    3    1.0
4  p2    5    2.0
5  p3    1    1.0
6  p3    2    2.0
7  p3    1    3.0
Run Code Online (Sandbox Code Playgroud)

考虑到@ALollz 的评论,替代解决方案:

df['count'] = df.assign(dif = (df.val.diff() != 0).astype(int)).groupby(['id']).dif.apply(lambda x : x.cumsum().rank(method='dense'))
Run Code Online (Sandbox Code Playgroud)

现在计数总是从组内的 1 开始。