熊猫:基于另一列的增加或重置计数

时间:2019-07-06 13:46:09

标签: python pandas

我有一个Pandas DataFrame,代表分数的时间序列。我想使用该分数基于以下条件来计算CookiePoints列:

  • 每一次得分都比以前的得分提高,都会得到一个CookiePoint。
  • 每次得分没有提高时,都会删除所有CookiePoints作为惩罚(CookiePoints设置为0)。
  • 可以将3个Cookiepoint兑换为Cookie。因此,在达到3后,CookiePoints计数应该为1(如果分数更高)或0(如果分数不是更高)。

请参见以下示例:

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,理想情况下只能使用矢量化操作。

1 个答案:

答案 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