假设我有以下数据。对于每个user_id,我想在每次差值为<= -2时获得累积计数,直到它达到正值。然后,计数应该重置为0,并保持在该值,直到遇到该用户的下一个<= -2,此时计数再次从1开始,直到达到下一个正值。结果应该等于我在cum_count中的结果。
df = pd.DataFrame({'user_id': [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3],
'difference_score': [0.0, 1.0, -2.5, -2.5, -0.5, -1.5, 2.25, 2.25, -1.86, 0.0, -0.33, -1.33, -2.33, 0.0, 1.0, -2.67, -0.67, -0.67, 0.67, -0.33, -0.33, 1.0],
'cum_count': [0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 2, 3, 0, 0, 0, 0]})
user_id difference_score cum_count
0 1 0.0000 0
1 1 1.0000 0
2 1 -2.5000 1
3 1 -2.5000 2
4 1 -0.5000 3
5 1 -1.5000 4
6 1 2.2500 0
7 1 2.2500 0
8 2 -1.8571 0
9 2 0.0000 0
10 2 -0.3333 0
11 2 -1.3333 0
12 2 -2.3333 1
13 2 0.0000 0
14 3 1.0000 0
15 3 -2.6667 1
16 3 -0.6667 2
17 3 -0.6667 3
18 3 0.6667 0
19 3 -0.3333 0
20 3 -0.3333 0
21 3 1.0000 0
编辑:基于你的解决方案mozway,我发现了几个实例,其中提出的解决方案没有产生预期的结果。抱歉,我的示例数据不够广泛。我现在扩展了上面的示例数据,以突出显示这一点。
例如,在下面的更新数据框中,第14行cum_count应该为0,因为它是一个新用户,并且差值为>2。但是,cum_count2产生一个1。
此外,一旦达到正值,计数重置为0,下一次遇到该用户的值<= -2时,计数应从1重新开始。但是,在第19行中,cum_count2继续从前一个计数开始计数。
更新后的cum_count列有我期望返回的值,与当前解决方案在cum_count2中返回的值相比…
df = pd.DataFrame({'user_id': [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3],
'difference_score': [0.0, 1.0, -2.5, -2.5, -0.5, -1.5, 2.25, 2.25, -1.86, 0.0, -0.33, -1.33, -2.33, -2.0, -1.0, -2.67, -0.67, -0.67, 0.67, -2.5, -0.33, 1.0],
'cum_count': [0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0]})
user_id difference_score cum_count cum_count2
0 1 0.00 0 0
1 1 1.00 0 0
2 1 -2.50 1 1
3 1 -2.50 2 2
4 1 -0.50 3 3
5 1 -1.50 4 4
6 1 2.25 0 0
7 1 2.25 0 0
8 2 -1.86 0 0
9 2 0.00 0 0
10 2 -0.33 0 0
11 2 -1.33 0 0
12 2 -2.33 1 1
13 2 -2.00 2 2
14 3 -1.00 0 1
15 3 -2.67 1 2
16 3 -0.67 2 3
17 3 -0.67 3 4
18 3 0.67 0 0
19 3 -2.50 1 5
20 3 -0.33 2 6
21 3 1.00 0 0
您可以使用掩码来定义开始和停止,识别连续匹配的值,并使用它来生成一个组来执行计数:
m1 = df['difference_score'].ge(0)
m2 = df['difference_score'].le(-2)
m3 = m2.groupby([df['user_id'], m1.cumsum()]).cummax()
group = (m3&~m3.groupby(df['user_id']).shift(fill_value=False)).cumsum()
df['cum_count'] = df.groupby(['user_id', group]).cumcount().add(1).where(m3, 0)
输出:
user_id difference_score cum_count m1 m2 m3 group
0 1 0.00 0 True False False 0
1 1 1.00 0 True False False 0
2 1 -2.50 1 False True True 1
3 1 -2.50 2 False True True 1
4 1 -0.50 3 False False True 1
5 1 -1.50 4 False False True 1
6 1 2.25 0 True False False 1
7 1 2.25 0 True False False 1
8 2 -1.86 0 False False False 1
9 2 0.00 0 True False False 1
10 2 -0.33 0 False False False 1
11 2 -1.33 0 False False False 1
12 2 -2.33 1 False True True 2
13 2 -2.00 2 False True True 2
14 3 -1.00 0 False False False 2
15 3 -2.67 1 False True True 3
16 3 -0.67 2 False False True 3
17 3 -0.67 3 False False True 3
18 3 0.67 0 True False False 3
19 3 -2.50 1 False True True 4
20 3 -0.33 2 False False True 4
21 3 1.00 0 True False False 4