我想将加权和应用于DataFrame。过去我用过
for sec_id, sec_df_unidx in grouped:
if sec_df_unidx.shape[0] > 3:
pd.rolling_sum(sec_df[added_cols], 4)
我想将加权平均值应用于最近乘以0.6的总和,第二乘0.2,第三和第四乘以0.1。
DF:
DATE ID VALUE
2012-12-31 A 100
2013-03-31 A 120
2013-06-30 A 140
2013-09-30 A 160
2013-12-31 A 180
2013-03-31 B 0
2013-06-30 B 5
2013-09-30 B 1
2013-12-31 B 3
2012-12-31 C 45
2013-03-31 C 46
2013-06-30 C 42
2013-09-30 C 30
2013-12-31 C 11
2012-12-31 D 18
2013-03-31 D 9
2013-06-30 D 13
2013-09-30 D 5
2013-12-31 D 11
2012-12-31 E 0
DF新列:
DATE ID VALUE Weight_Sum
2012-12-31 A 100 NaN
2013-03-31 A 120 NaN
2013-06-30 A 140 NaN
2013-09-30 A 160 146
2013-12-31 A 180 166
2013-03-31 B 0 NaN
2013-06-30 B 5 NaN
2013-09-30 B 1 NaN
2013-12-31 B 3 2.5
2012-12-31 C 45 NaN
2013-03-31 C 46 NaN
2013-06-30 C 42 NaN
2013-09-30 C 30 35.5
2013-12-31 C 11 21.4
2012-12-31 D 18 NaN
2013-03-31 D 9 NaN
2013-06-30 D 13 NaN
2013-09-30 D 5 8.3
2013-12-31 D 11 9.8
2012-12-31 E 0 NaN
我可以使用rolling_apply或rolling_sum执行此操作吗?或者我必须做一个for循环吗?
谢谢。
答案 0 :(得分:2)
我认为你可以在普通rolling_apply
调用的函数中执行groupby/apply
。如下所示:
def roll_wsum(g,w,p):
rsum = pd.rolling_apply(g.values,p,lambda x: np.dot(w,x),min_periods=p)
return pd.Series(rsum,index=g.index)
weights = np.array([0.1,0.1,0.2,0.6])
df['wsum'] = df.groupby('ID')['VALUE'].apply(roll_wsum,weights,4)
print df
输出:
DATE ID VALUE wsum
0 2012-12-31 A 100 NaN
1 2013-03-31 A 120 NaN
2 2013-06-30 A 140 NaN
3 2013-09-30 A 160 146.0
4 2013-12-31 A 180 166.0
5 2013-03-31 B 0 NaN
6 2013-06-30 B 5 NaN
7 2013-09-30 B 1 NaN
8 2013-12-31 B 3 2.5
9 2012-12-31 C 45 NaN
10 2013-03-31 C 46 NaN
11 2013-06-30 C 42 NaN
12 2013-09-30 C 30 35.5
13 2013-12-31 C 11 21.4
14 2012-12-31 D 18 NaN
15 2013-03-31 D 9 NaN
16 2013-06-30 D 13 NaN
17 2013-09-30 D 5 8.3
18 2013-12-31 D 11 9.8
19 2012-12-31 E 0 NaN
所以,我只是按'ID'对数据进行分组,然后将一个组的'VALUE'列发送到我的roll_wsum函数(以及加权和和句点的权重)。 roll_wsum
函数调用rolling_apply
并将简单的lambda函数提供给rolling_apply
:'VALUE'的点积和权重。此外,强制min_periods=4
条件至关重要,因为我们需要数组的长度(权重和df ['VALUE']。值)是相同的。
鉴于我使用点积来计算加权和,它可能无法按照您想要的方式处理缺失值。因此,例如,您可能更喜欢以下内容(尽管它对示例数据没有影响):
def roll_wsum(g,w,p):
rsum = pd.rolling_apply(g.values,p,lambda x: np.nansum(w*x),min_periods=p)
return pd.Series(rsum,index=g.index)
weights = np.array([0.1,0.1,0.2,0.6])
df['wsum'] = df.groupby('ID')['VALUE'].apply(roll_wsum,weights,4)