达到阈值后将累积值设置为常数
Posted
技术标签:
【中文标题】达到阈值后将累积值设置为常数【英文标题】:Setting cumulative values to constant after it reaches threshold 【发布时间】:2018-07-12 07:42:38 【问题描述】:我有一个包含每月累积值的 pandas 时间序列。
如果在一个月的某个日期,该值变成了某个数字,我需要将其余天数设置为 1000。
例如
df:
Date cummulative_value
1/8/2017 -3
1/9/2017 -6
1/10/2017 -72
1/11/2017 500
1/26/2017 575
2/7/2017 -5
2/14/2017 -6
2/21/2017 -6
我的截止值是-71,所以在上面的例子中我需要实现以下目标:
Date cummulative_value
1/8/2017 -3
1/9/2017 -6
1/10/2017 1000
1/11/2017 1000
1/26/2017 1000
2/7/2017 -5
2/14/2017 -6
2/21/2017 -6
我正在尝试在 pandas 中利用 groupby
,但我不知道该怎么做。任何其他更有效的方法也会有所帮助。
【问题讨论】:
不是没有考虑到哪个月的累计值 每月是否有截止值? -71 是每个月的截止日期 【参考方案1】:使用groupby
和cumprod
:
df['cummulative_value'] = (df.groupby(df['Date'].dt.strftime('%Y%m'))['cummulative_value']
.transform(lambda x: np.where(x.ge(-71).cumprod(),x,1000)))
print(df)
输出:
Date cummulative_value
0 2017-01-08 -3
1 2017-01-09 -6
2 2017-01-10 1000
3 2017-01-11 1000
4 2017-01-26 1000
5 2017-02-07 -5
6 2017-02-14 -6
7 2017-02-21 -6
【讨论】:
我永远无法找到您的解决方案.. 我什至需要了解“transform”和“gt”是什么.. 谢谢 基本上,您使用日期的字符串格式按月分组为YYYYMM,然后您可以将您的cum_value分为1和0,每个值大于或等于(ge)-71,一次值是零,让它为零。 cumprod 对此有好处。最后,像 if then 语句一样使用 np.where,if 1 then return cum_val else return constant value。 如果我希望截止日期在 2017 年 1 月 11 日有效,我将如何修改代码。即让第一个满足条件的人留下 我在你的回答中没有看到任何 cumsum() ? @Zanam 抱歉 cumprod()【参考方案2】:这是一种涉及创建掩码的方法:
df.set_index(pd.to_datetime(df['Date'], format="%m/%d/%Y"), inplace=True)
mask = df['cummulative_value'].lt(-71).groupby(df.index.month).cumsum()
# Date
# 2017-01-08 False
# 2017-01-09 False
# 2017-01-10 True
# 2017-01-11 True
# 2017-01-26 True
# 2017-02-07 False
# 2017-02-14 False
# 2017-02-21 False
df.loc[mask, 'cummulative_value'] = 1000
df.reset_index(drop=True)
# Date cummulative_value
# 0 1/8/2017 -3
# 1 1/9/2017 -6
# 2 1/10/2017 1000
# 3 1/11/2017 1000
# 4 1/26/2017 1000
# 5 2/7/2017 -5
# 6 2/14/2017 -6
# 7 2/21/2017 -6
【讨论】:
我无法让您的解决方案运行。它在“掩码”之后的第三行出错 @Zanam 我刚刚从头开始在示例 df 上再次运行它(在 python 3.6.2 和 pandas 0.20.3 上)并且没有遇到错误。如果您希望我仔细查看,请随时告诉我错误是什么。以上是关于达到阈值后将累积值设置为常数的主要内容,如果未能解决你的问题,请参考以下文章