2016-12-16 80 views
2

对于一些数据预处理,我有一个巨大的数据框,我需要组内的历史性能。然而,由于它是针对目标前一周运行的预测模型,因此我无法使用在该周之间发生的任何数据。每组每天有不定数量的行,这意味着我不能总是在扩展函数上使用移位来丢弃最后7个值,我必须以某种方式调整它之前的行的日期时间。我可以编写自己的函数来适用于团队,但是我的经验通常非常缓慢(尽管很灵活)。这是我做的不对日期空调和只盯着前面的记录:有条件扩展群组聚合熊猫

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

5代表,我想至少5样本大小或把它放到NaN的。

小例子与A组至少提前一周内aggr_mean看着所有样本的平均值:使用@ JulienMarrec的更好的例子

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) 
+0

你可以发布你的数据样本吗? [mcve] –

+0

是的,忘了这么做,只是加了:) –

回答

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更有用

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

+0

你可以在'['group','dt']'上执行'merge_asof'吗?因为OP的要求是在组内做的(不是非常清楚,因为样本数据只有一个组,但它是在前面写的) –

+1

我现在正在努力......尽量不要睡着;-) – piRSquared

+0

由于我遗憾地没有清楚地陈述,可能会有重复取样方法不允许的多行的日子,我可以以类似的方式使用旧的方法,虽然对吗? –

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

+0

这看起来像一个不错的方法,但是如果有几行具有相同的dt,这种重新采样方法是否仍然有效? –

+0

我不知道这是一个要求...不,它会弄乱重量。你不得不做我的答案之间的混合(GROUPBY,因为你要通过团体做,但没有重新取样,而不是移(频率=“7D”))和@ piRSquared的merge_asof –

+0

谢谢,对不起,我不太清楚,也应该在示例中添加它。 –