我想对一个数据框应用滚动函数,该数据框由两列分组,并具有重复的日期条目。具体来说,“freq”和“window”都是datetime值,而不仅仅是整数。
原则上,我试图结合如何在pandas中应用分组对象中的滚动函数和pandas滚动最后五分钟的总和方法。 输入 以下是数据的示例,其中一个id = 33,尽管我们期望有几个id。
例如,在右包含的结束日期2017-02-13,我们对3天的时间段2017-02-11至2017-02-13进行采样。在此期间,id=33的总和A点数为1+1+1+4 = 7。
尝试使用pd.rolling_sum进行分组的尝试如下所示,由于日期重复而未能成功。
当然,设置一个循环来遍历唯一的id ID,选择df_id = df[df['id']==ID],并在时间段上求和确实可以工作,但计算密集且不能充分利用groupby的向量化。感谢@jezrael迄今为止提出的好建议。
注: Pandas版本=0.20.1 我有点困惑为什么这里rolling()的文档https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html建议“window”参数可以是int或offset,但尝试df.rolling(window='3D',...)时我得到
原则上,我试图结合如何在pandas中应用分组对象中的滚动函数和pandas滚动最后五分钟的总和方法。 输入 以下是数据的示例,其中一个id = 33,尽管我们期望有几个id。
X = [{'date': '2017-02-05', 'id': 33, 'item': 'A', 'points': 20},
{'date': '2017-02-05', 'id': 33, 'item': 'B', 'points': 10},
{'date': '2017-02-06', 'id': 33, 'item': 'B', 'points': 10},
{'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
{'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
{'date': '2017-02-11', 'id': 33, 'item': 'A', 'points': 1},
{'date': '2017-02-13', 'id': 33, 'item': 'A', 'points': 4}]
# df = pd.DataFrame(X) and reindex df to pd.to_datetime(df['date'])
df
id item points
date
2017-02-05 33 A 20
2017-02-05 33 B 10
2017-02-06 33 B 10
2017-02-11 33 A 1
2017-02-11 33 A 1
2017-02-11 33 A 1
2017-02-13 33 A 4
目标
每两天对每个'id'进行一次样本采集(freq='2d'),并返回前三天(window='3D')中每个项目的总点数之和,包括结束日期在内。
期望输出
id A B
date
2017-02-05 33 20 10
2017-02-07 33 20 30
2017-02-09 33 0 10
2017-02-11 33 3 0
2017-02-13 33 7 0
例如,在右包含的结束日期2017-02-13,我们对3天的时间段2017-02-11至2017-02-13进行采样。在此期间,id=33的总和A点数为1+1+1+4 = 7。
尝试使用pd.rolling_sum进行分组的尝试如下所示,由于日期重复而未能成功。
df.groupby(['id', 'item'])['points'].apply(pd.rolling_sum, freq='4D', window=3)
ValueError: cannot reindex from a duplicate axis
请注意,从http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.rolling_apply.html文档中可以看出,'window'是一个表示样本周期大小的整数,而不是要采样的天数。
我们也可以尝试重新采样并使用last,但是所需的3天回顾似乎没有被使用。
df.groupby(['id', 'item'])['points'].resample('2D', label='right', closed='right').\
apply(lambda x: x.last('3D').sum())
id item date
33 A 2017-02-05 20
2017-02-07 0
2017-02-09 0
2017-02-11 3
2017-02-13 4
B 2017-02-05 10
2017-02-07 10
当然,设置一个循环来遍历唯一的id ID,选择df_id = df[df['id']==ID],并在时间段上求和确实可以工作,但计算密集且不能充分利用groupby的向量化。感谢@jezrael迄今为止提出的好建议。
注: Pandas版本=0.20.1 我有点困惑为什么这里rolling()的文档https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html建议“window”参数可以是int或offset,但尝试df.rolling(window='3D',...)时我得到
raise ValueError("window must be an integer")
。似乎上述文档与rolling的最新代码./core/window.py https://github.com/pandas-dev/pandas/blob/master/pandas/core/window.py不一致。elif not is_integer(self.window):
raise ValueError("window must be an integer")
np.nan
后使用pd.Series.first_valid_index
或pd.Series.last_valid_index
。你也可以在numpy
中使用一些其他技巧。 - piRSquared