在30个非日期天内滚动求和
我一直在绞尽脑汁,想找出最好的方法来解决这个问题。我想计算过去30天的滚动总和,但我的“天”这一列并不是日期时间格式。
这里有一些示例数据:
df = pd.DataFrame({'client': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'],
'day': [319, 323, 336, 352, 379, 424, 461, 486, 496, 499, 303, 334, 346, 373, 374, 395, 401, 408, 458, 492],
'foo': [5.0, 2.0, np.nan, np.nan, np.nan, np.nan, np.nan, 7.0, np.nan, np.nan, 8.0, 7.0, 22.0, np.nan, 13.0, np.nan, np.nan, 5.0, 11.0, np.nan]}
>>> df
client day foo
0 A 319 5.0
1 A 323 2.0
2 A 336 NaN
3 A 352 NaN
4 A 379 NaN
5 A 424 NaN
6 A 461 NaN
7 A 486 7.0
8 A 496 NaN
9 A 499 NaN
10 B 303 8.0
11 B 334 7.0
12 B 346 22.0
13 B 373 NaN
14 B 374 13.0
15 B 395 NaN
16 B 401 NaN
17 B 408 5.0
18 B 458 11.0
19 B 492 NaN
我想要一个新列,显示每30天的'foo'的滚动总和。
到目前为止,我尝试过:
df['foo_30day'] = df.groupby('client').rolling(30, on='day', min_periods=1)['foo'].sum().values
但看起来它只是计算了最后30行的总和。
我还在考虑是否可以把“天”这一列改成日期时间格式,然后使用 rolling('30D')
,但我不确定这样做是否合适,或者该怎么做。我也尝试过用groupby重新索引来扩展“天”这一列,然后简单地使用 rolling(30)
,但对我来说效果不佳。
任何建议都会非常感激。
1 个回答
2
你可以把天数转换成日期时间格式,然后使用 window='30D'
。这样,天数就会被转换成日期时间,从Pandas能处理的最早日期开始,也就是1970年1月1日。
你还可以选择用 to_datetime
中的 origin
属性来指定一个起始日期,不过在你的例子里,这个起始日期并不重要。
df = df.sort_values(["client", "day"]).reset_index(drop=True)
df["day_datetime"] = pd.to_datetime(df["day"], unit="D")
df["foo_30day"] = (
df.groupby("client")
.rolling("30D", on="day_datetime", min_periods=1)["foo"]
.sum()
.values
)
client day foo day_datetime foo_30day
0 A 319 5.0 1970-11-16 5.0
1 A 323 2.0 1970-11-20 7.0
2 A 336 NaN 1970-12-03 7.0
3 A 352 NaN 1970-12-19 2.0
4 A 379 NaN 1971-01-15 NaN
5 A 424 NaN 1971-03-01 NaN
6 A 461 NaN 1971-04-07 NaN
7 A 486 7.0 1971-05-02 7.0
8 A 496 NaN 1971-05-12 7.0
9 A 499 NaN 1971-05-15 7.0
10 B 303 8.0 1970-10-31 8.0
11 B 334 7.0 1970-12-01 7.0
12 B 346 22.0 1970-12-13 29.0
13 B 373 NaN 1971-01-09 22.0
14 B 374 13.0 1971-01-10 35.0
15 B 395 NaN 1971-01-31 13.0
16 B 401 NaN 1971-02-06 13.0
17 B 408 5.0 1971-02-13 5.0
18 B 458 11.0 1971-04-04 11.0
19 B 492 NaN 1971-05-08 NaN