我有一个Pandas DataFrame,代表分数的时间序列。我想使用该分数基于以下条件来计算CookiePoints列:
请参见以下示例:
Score CookiePoints
14 0
13 0
14 1
17 2
17 0
19 1
20 2
22 3
23 1
17 0
19 1
20 2
22 3
21 0
请注意,这是minimal, reproducible example。解决方案必须使用Pandas DataFrame,理想情况下只能使用矢量化操作。
答案 0 :(得分:3)
这当然是一个棘手的问题,但仍然可以在Pandas中解决。 (更新V3解决方案)
版本3(OneLiner)
score = pd.Series([14,13,14,17,17,19,20,22,23,17,19,20,22,21])
result = score.diff().gt(0).pipe(lambda x:x.groupby((~x).cumsum()).cumsum().mod(3).replace(0,3).where(x,0).map(int))
版本2
score = pd.Series([14,13,14,17,17,19,20,22,23,17,19,20,22,21])
mask= score.diff()>0
result = mask.groupby((~mask).cumsum()).cumsum().mod(3).replace(0,3).where(mask,0).map(int)
版本1
score = pd.Series([14,13,14,17,17,19,20,22,23,17,19,20,22,21])
mask= score.diff()>0 # Identify score going up
mask
0 False
1 False
2 True
3 True
4 False
5 True
6 True
7 True
8 True
9 False
10 True
11 True
12 True
13 False
dtype: bool
# Use False Cumsum to group True values
group = (mask==False).cumsum()
group
0 1
1 2
2 2
3 2
4 3
5 3
6 3
7 3
8 3
9 4
10 4
11 4
12 4
13 5
dtype: int64
# Groupby False Cumsum
temp = mask.groupby(group).cumsum().map(int)
temp
0 0
1 0
2 1
3 2
4 0
5 1
6 2
7 3
8 4
9 0
10 1
11 2
12 3
13 0
dtype: int64
# Fix Cap at 3
# result = temp.where(temp<=3,temp.mod(3)) # This is Wrong.
result = temp.mod(3).replace(0,3).where(mask,0)
result
0 0
1 0
2 1
3 2
4 0
5 1
6 2
7 3
8 1
9 0
10 1
11 2
12 3
13 0
dtype: int64