计算简单移动平均线 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
我目前正在尝试计算几只股票的数据集的简单移动平均线。我只在两家公司(和 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