pandas - 熊猫:如何纠正小于以前的值和一些模式
问题描述
我有以下时间序列:
2017-11-01 200.000000
2017-12-01 394.000000
2018-01-01 537.000000
2018-02-01 537.000000
2018-03-01 537.000000
2018-04-01 537.000000
2018-05-01 537.000000
2018-06-01 537.000000
2018-07-01 137.000000
2018-08-01 88.000000
2018-09-01 10.000000
2018-10-01 100.000000
2018-11-01 100.000000
2018-12-01 111.000000
2019-01-01 362.000000
2019-02-01 563.000000
2019-03-01 706.000000
2019-04-01 750.000000
2019-05-01 785.000000
2019-06-01 785.000000
我正在处理一个周期性的时间序列,其中的值是从 9 月到 8 月累积的。9 月的值应该低于之前的值。前几个月不是这样!所以,我的时间序列在 2018-07-01 和 2018-08-01 是错误的,但在 2018-09-01 是正确的。我想用 2018-06-01 (537.0) 中的最后一个值替换这些值。
我使用了 .shift(1) pandas 选项,但我只能用 6 月的值替换 7 月的值,但我用之前的 7 月值替换了 8 月!这是我使用的代码:
new_df = pd.DataFrame({'date': new_df.index.tolist(), 'vals': new_df.tolist()}) # from df to ts
new_df['shift_values'] = new_df['vals'].shift(1) # create a col with previous values
new_df['diff'] = new_df.apply(lambda x: x['vals']-x['shift_values'], axis=1) # calculate the difference
new_df['valore_finale'] = new_df.apply(lambda x: x['vals'] if x['date'] == '2019-09-01' else(x['vals'] if x['diff']>0 else x['shift_values']), axis=1)
2017-11-01 200.000000
2017-12-01 394.000000
2018-01-01 537.000000
2018-02-01 537.000000
2018-03-01 537.000000
2018-04-01 537.000000
2018-05-01 537.000000
2018-06-01 537.000000
2018-07-01 537.000000 # changed
2018-08-01 537.000000 # changed
2018-09-01 10.000000 # no changed
2018-10-01 100.000000
2018-11-01 100.000000
2018-12-01 111.000000
2019-01-01 362.000000
2019-02-01 563.000000
2019-03-01 706.000000
2019-04-01 750.000000
2019-05-01 785.000000
2019-06-01 785.000000
解决方案
首先转换为 datetime 以便能够mask
根据您要修改的月份使用:
df['date']=pd.to_datetime(df['date'])
然后使用Series.mask把作为NaN
你想要改变的值,然后用Series.ffill填充
df['vals']=df['vals'].mask((df['date'].dt.month<9) & (df['vals']<df['vals'].shift())).ffill()
print(df)
date vals
0 2017-11-01 200.0
1 2017-12-01 394.0
2 2018-01-01 537.0
3 2018-02-01 537.0
4 2018-03-01 537.0
5 2018-04-01 537.0
6 2018-05-01 537.0
7 2018-06-01 537.0
8 2018-07-01 537.0
9 2018-08-01 537.0
10 2018-09-01 10.0
11 2018-10-01 100.0
12 2018-11-01 100.0
13 2018-12-01 111.0
14 2019-01-01 362.0
15 2019-02-01 563.0
16 2019-03-01 706.0
17 2019-04-01 750.0
18 2019-05-01 785.0
19 2019-06-01 785.0
如果对于 1 月,必须不考虑上一年 12 月的值,则必须使用groupby。
g=df.groupby(df['date'].dt.year)['vals']
df['vals']=df['vals'].mask( (df['vals']<g.shift())&(df['date'].dt.month<9) ).ffill()
细节
Series.shift用于与前一个进行比较。
datetime.dt.month用于获取 9 月之前的月份
推荐阅读
- python - 网页抓取——find_all() 返回空列表
- arrays - 切片数组文字
- ios - 未调用 userNotificationCenter(_:didReceive:withCompletionHandler:)
- javascript - 使用数据变量动态设置属性样式填充
- php - 文件上传但名称为空
- sql - postgres中如何将csv文件加载到多个表中(主要关注最佳实践)
- graphics - 了解 Oren-Nayar 反射模型
- pandas - 计算过去满足类似于 excel 的 COUNTIF 条件的相对行数
- reactjs - 是否有正确的方法将对象用作 useEffect 中的依赖项?
- excel - 运行时错误“13”VBA 代码突出显示最后一个数据点