在30个非日期天内滚动求和

1 投票
1 回答
60 浏览
提问于 2025-04-13 00:44

我一直在绞尽脑汁,想找出最好的方法来解决这个问题。我想计算过去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

撰写回答