给出以下格式的熊猫数据框:
toy = pd.DataFrame({
'id': [1,2,3,
1,2,3,
1,2,3],
'date': ['2015-05-13', '2015-05-13', '2015-05-13',
'2016-02-12', '2016-02-12', '2016-02-12',
'2018-07-23', '2018-07-23', '2018-07-23'],
'my_metric': [395, 634, 165,
144, 305, 293,
23, 395, 242]
})
# Make sure 'date' has datetime format
toy.date = pd.to_datetime(toy.date)
my_metric
列包含一些(随机)量度,我希望以id
列为条件来计算时间的移动平均值
并在指定的时间间隔内指定自己。我将此时间间隔称为“回溯时间”;这可能是5分钟
或2年。为了确定哪些观测值将包含在回溯计算中,我们使用date
列(如果愿意,可以是索引)。
令我沮丧的是,我发现使用pandas内置函数不容易执行这样的过程,因为我需要有条件地执行计算
在id
上进行,并且同时只能根据回溯时间内的观测值进行计算(使用date
列进行检查)。因此,对于每个id
-date
组合,输出数据帧应由一行组成,其中my_metric
列现在是包含在回溯时间内的所有观测值的平均值(例如2年,包括今天的日期。
为清楚起见,在使用2年回溯时间时,我提供了具有所需输出格式的图形(对超大图形表示歉意):
我有一个解决方案,但是它没有利用特定的熊猫内置函数,并且可能不是最优的(列表理解和单个for循环的组合)。我正在寻找的解决方案不会使用for循环,因此更具可伸缩性/效率/更快。
谢谢!
答案 0 :(得分:0)
计算回溯时间:(当前年份-2年)
from dateutil.relativedelta import relativedelta
from dateutil import parser
import datetime
In [1691]: dt = '2018-01-01'
In [1695]: dt = parser.parse(dt)
In [1696]: lookback_time = dt - relativedelta(years=2)
现在,根据回溯时间过滤数据框并计算滚动平均值
In [1722]: toy['new_metric'] = ((toy.my_metric + toy[toy.date > lookback_time].groupby('id')['my_metric'].shift(1))/2).fillna(toy.my_metric)
In [1674]: toy.sort_values('id')
Out[1674]:
date id my_metric new_metric
0 2015-05-13 1 395 395.0
3 2016-02-12 1 144 144.0
6 2018-07-23 1 23 83.5
1 2015-05-13 2 634 634.0
4 2016-02-12 2 305 305.0
7 2018-07-23 2 395 350.0
2 2015-05-13 3 165 165.0
5 2016-02-12 3 293 293.0
8 2018-07-23 3 242 267.5
答案 1 :(得分:0)
因此,经过一番修补,我找到了一个可以充分概括的答案。我使用了一个略有不同的“玩具”数据框(与我的情况稍相关)。为了完整起见,以下是数据:
现在考虑以下代码:
# Define a custom function which groups by time (using the index)
def rolling_average(x, dt):
xt = x.sort_index().groupby(lambda x: x.time()).rolling(window=dt).mean()
xt.index = xt.index.droplevel(0)
return xt
dt='730D' # rolling average window: 730 days = 2 years
# Group by the 'id' column
g = toy.groupby('id')
# Apply the custom function
df = g.apply(rolling_average, dt=dt)
# Massage the data to appropriate format
df.index = df.index.droplevel(0)
df = df.reset_index().drop_duplicates(keep='last', subset=['id', 'date'])
结果符合预期: