我是python的新手,并且一直试图在pandas数据框中计算一些简单的滚动加权平均值。我有一个观察数据框df
和一个权重w
的数据框。我创建了一个新的数据框,用于保存这两组值dot
。
由于w
的维度较小,我使用for循环计算行的加权平均值,前导行的行数等于w
的长度。
更清楚的是,我的设置如下:
import pandas as pd
df = pd.DataFrame([0,1,2,3,4,5,6,7,8], index = range(0,9))
w = pd.DataFrame([0.1,0.25,0.5], index = range(0,3))
dot = pd.DataFrame(0, columns = ['dot'], index = df.index)
for i in range(0,len(df)):
df.loc[i] = sum(df.iloc[max(1,(i-3)):i].values * w.iloc[-min(3,(i-1)):4].values)
我希望结果如下(即当i = 4
)
dot.loc[4] = sum(df.iloc[max(1,(4-3)):4].values * w.iloc[-min(3,(4-1)):4].values)
print dot.loc[4] #2.1
但是,当运行上面的for循环时,我收到错误:
ValueError: operands could not be broadcast together with shapes (0,1) (2,1)
这是我感到困惑的地方 - 我认为这必须与我将i
调用iloc
的方式有关,因为当我手动计算它时我没有收到形状错误,就像在上面有4
的示例。但是,看看其他示例和文档,我不明白为什么会这样......任何帮助都表示赞赏。
答案 0 :(得分:2)
您的第一个问题是您正在尝试将两种不同大小的数组相乘。例如,当i=0
for循环的不同部分返回
df.iloc[max(1,(0-3)):0].values.shape
# (0,1)
w.iloc[-min(3,(0-1)):4].values.shape
# (2,1)
这正是你得到的错误。我可以想到使数组可倍增的最简单方法是使用concatenation使用前导零填充数据帧。
df2 = pd.concat([pd.Series([0,0]),df], ignore_index=True)
df2
0
0 0
1 0
2 0
3 1
4 2
5 3
6 4
7 5
8 6
9 7
10 8
虽然您现在可以使用for循环(稍微调整一下):
for i in range(len(df)):
dot.loc[i] = sum(df2.iloc[max(0,(i)):i+3].values * w.values)
更好的方式可能就是JohnE suggested使用pandas内置的rolling和apply函数的方式,通过摆脱你的for循环
import numpy as np
df2.rolling(3,min_periods=3).apply(lambda x: np.dot(x,w))
0
0 NaN
1 NaN
2 0.00
3 0.50
4 1.25
5 2.10
6 2.95
7 3.80
8 4.65
9 5.50
10 6.35
您还可以drop前两个填充行和reset the index
df2.rolling(3,min_periods=3).apply(lambda x: np.dot(x,w)).drop([0,1]).reset_index(drop=True)
0
0 0.00
1 0.50
2 1.25
3 2.10
4 2.95
5 3.80
6 4.65
7 5.50
8 6.35