条件扩展组聚合熊猫

时间:2016-12-16 09:06:42

标签: python pandas

对于某些数据预处理,我有一个巨大的数据框,我需要在组内进行历史性能。但是,由于它是针对在目标之前一周运行的预测模型,因此我无法使用在该周之间发生的任何数据。每组每天有一个可变数量的行,这意味着我不能总是通过使用扩展函数的移位来丢弃最后7个值,我必须以某种方式调整它之前的行的日期时间。我可以编写自己的函数来应用于组,但这通常在我的经验中非常慢(尽管是灵活的)。这就是我如何在没有条件约束的情况下做到这一点,只看以前的记录:

df.loc[:, 'new_col'] = df_gr['old_col'].apply(lambda x: x.expanding(5).mean().shift(1))

5代表我想要至少5的样本大小或将其放入NaN。

至少一周前,aggr_mean查看A组中所有样本的平均值的小例子:

group | dt       | value  | aggr_mean
A     | 01-01-16 | 5      | NaN
A     | 03-01-16 | 4      | NaN
A     | 08-01-16 | 12     | 5 (only looks at first row)
A     | 17-01-16 | 11     | 7 (looks at first three rows since all are 
                               at least a week earlier)

2 个答案:

答案 0 :(得分:3)

新答案
使用@ JulienMarrec的更好的例子

dt           group  value   
2016-01-01     A      5
2016-01-03     A      4
2016-01-08     A     12
2016-01-17     A     11
2016-01-04     B     10
2016-01-05     B      5
2016-01-08     B     12
2016-01-17     B     11

条件df更有用

d1 = df.drop('group', 1)
d1.index = [df.group, df.groupby('group').cumcount().rename('gidx')]
d1

enter image description here

创建一个自定义函数来完成旧答案所做的事情。然后在groupby

中应用它
def lag_merge_asof(df, lag):
    d = df.set_index('dt').value.expanding().mean()
    d.index = d.index + pd.offsets.Day(lag)
    d = d.reset_index(name='aggr_mean')
    return pd.merge_asof(df, d)

d1.groupby(level='group').apply(lag_merge_asof, lag=7)

enter image description here

我们可以使用此

进行一些格式化
d1.groupby(level='group').apply(lag_merge_asof, lag=7) \
    .reset_index('group').reset_index(drop=True)

enter image description here

旧答案

通过将日期偏移7天来创建lookback数据框,然后将其用于pd.merge_asof

lookback = df.set_index('dt').value.expanding().mean()

lookback.index += pd.offsets.Day(7)
lookback = lookback.reset_index(name='aggr_mean')

lookback

enter image description here

pd.merge_asof(df, lookback, left_on='dt', right_on='dt')

enter image description here

答案 1 :(得分:3)

鉴于此数据框,我添加了另一个组,以便更清楚地了解发生了什么:

dt           group  value                               
2016-01-01     A      5
2016-01-03     A      4
2016-01-08     A     12
2016-01-17     A     11
2016-01-04     B     10
2016-01-05     B      5
2016-01-08     B     12
2016-01-17     B     11

让我们加载它:

df = pd.read_clipboard(index_col=0, sep='\s+', parse_dates=True)

现在我们可以使用groupby,每天重新采样,并进行7天的转换,并取平均值:

x = df.groupby('group')['value'].apply(lambda gp: gp.resample('1D').mean().shift(7).expanding().mean())

现在您可以将left合并到您的df中:

merged = df.reset_index().set_index(['group','dt']).join(x, rsuffix='_aggr_mean', how='left')
merged

enter image description here