计算简单移动平均线 pandas for loop

Calculating simple moving average pandas for loop

我目前正在尝试计算几只股票的数据集的简单移动平均线。我只在两家公司(和 4 天的时间)上尝试代码以使其工作简单,但输出似乎存在一些问题。下面是我的代码。

for index, row in df3.iloc[4:].iterrows():
    if df3.loc[index,'CompanyId'] == df3.loc[index-4,'CompanyId']:
        df3['SMA4'] = df3.iloc[:,1].rolling(window=4).mean()
    else:
        df3['SMA4'] = 0

这是输出:Output

数据框按日期和公司 ID 排序。所以需要发生的是,当公司 ID 不等于代码中所述时,输出应该为零,因为我无法计算两家不同公司的移动平均值。相反,它会输出两家公司的移动平均线,例如第 7、8、9 行。

使用groupby.rolling

df['SMA4']=df.groupby('CompanyId',sort=False).rolling(window=4).Price.mean().reset_index(drop='CompanyId')
print(df)

    CompanyId  Price   SMA4
0           1     75    NaN
1           1     74    NaN
2           1     77    NaN
3           1     78  76.00
4           1     80  77.25
5           1     79  78.50
6           1     80  79.25
7           0     10    NaN
8           0      9    NaN
9           0     12    NaN
10          0     11  10.50
11          0     11  10.75
12          0      8  10.50
13          0      9   9.75
14          0      8   9.00
15          0      8   8.25
16          0     11   9.00

虽然 ansev 认为您应该使用专用函数是正确的,因为手动循环要慢得多,但我想说明为什么您的代码不起作用: 在 if 分支和 else 分支中,整个 SMA4 列都被分配给 (df3['SMA4']),并且因为在循环的最后一个 运行 中,if 语句为真,所以 else 语句不' 有任何影响,SMA4 永远不会为 0。因此,要解决这个问题,您可以先创建填充有滚动平均值的列(请注意,这不在 for 循环中):

df3['SMA4'] = df3.iloc[:,1].rolling(window=4).mean()

然后你 运行 将无效行设置为 0 的循环(尽管 nan 会更好。我保留了其他错误,假设 ansev 答案中的数字是正确的):

for index, row in df3.iloc[4:].iterrows(): 
    if df3.loc[index,'CompanyId'] != df3.loc[index-4,'CompanyId']: 
        df3.loc[index,'SMA4'] = 0 

输出(可能仍然有问题):

    CompanyId  Price   SMA4
0           1     75    NaN
1           1     74    NaN
2           1     77    NaN
3           1     78  76.00
4           1     80  77.25
5           1     79  78.50
6           1     80  79.25
7           2     10   0.00
8           2      9   0.00
9           2     12   0.00
10          2     11   0.00
11          2     11  10.75
12          2      8  10.50
13          2      9   9.75
14          2      8   9.00
15          2      8   8.25
16          2     11   9.00