计算移动平均线
Calculating a moving average
我很难在我的函数中实现移动平均公式。
我花了很长时间才找到代码所在的位置。
有没有我可以去的图书馆?
输入:
ma([2,3,4,3,2,6,9,3,2,1], 4)
预期输出:
[None, None, None, 3.0, 3.0, 3.75, 5.0, 5.0, 5.0, 3.75]
我的输出:
[None, None, 0.0, 3.0, 3.75, 5.0, 5.0, None, None, None]
我 运行 遇到的问题是我的结果的中间部分是正确的,但其余部分是个谜。
- 为什么列表中的最后三个值 return None?
def ma(价格, n):
ma = []
sums = []
s = 0
ave = 0
for idx, i in enumerate(prices):
s += i
sums.append(s)
print('idx: ' + str(idx))
print('list of sums ' + str(sums))
#print('sum ' + str(s))
if i >= n+1:
print('sums[idx] ' + str(sums[idx]))
print('sums[idx-n] ' + str(sums[idx-n]))
ave = (sums[idx] - sums[idx-n]) / n
print('ave ' + str(ave))
ma.append(ave)
print('ma ' + str(ma))
else:
m = None
ma.append(m)
print('ma ' + str(ma))
(抱歉所有这些 print
函数调用,但我真的很想找到问题的根源)。
您的代码中还有其他几个逻辑错误。我试图更正它以使其按您的意愿工作。以下只是 for 循环的修改版本。休息保持不变。 added/modified 行用注释
突出显示
for idx, i in enumerate(prices):
s += i
sums.append(s)
if idx == n-1: # Added
ave = (sums[idx]) / n # Added
ma.append(ave) # Added
elif idx >= n: # modified
ave = (sums[idx] - sums[idx-n]) / n
ma.append(ave)
else:
ma.append(None) # removed extra variable m
问题是您使用了错误的变量作为索引:
一个主要问题是您使用
if i >= n+1:
您应该使用:
if idx >= n+1:
此外,我添加了一个 if 语句来处理前三个元素的平均值。
现在
moving_average([2,3,4,5,8,5,4,3,2,1], 3)
给出以下输出(您可以稍后四舍五入):
[None, None, 3.0, 4.0, 5.666666666666667, 6.0, 5.666666666666667, 4.0, 3.0, 2.0]
您的程序返回 9-9 / 3 = 0
的原因是负索引。当 idx
是 2
时,sums[idx-n]
表示 sums[-1]
,它指向列表的最后一项 9
。 Understanding Python's slice notation 可以帮助解释这一点。
您还可以使用列表切片巧妙地对输入列表进行分区并计算列表分区的平均值来解决此问题:
def moving_average(data,window):
"""The partitions begin with window-1 None. Then follow partial lists, containing
window-sized elements. We do this only up to len(data)-window+1 as the following
partitions would have less then window elements."""
parts = [None]*(window-1) + [ data[i:i+window] for i in range(len(data)-window+1)]
# The None's The sliding window of window elements
# we return None if the value is None else we calc the avg
return [ sum(x)/window if x else None for x in parts]
print( moving_average([2,3,4,5,8,5,4,3,2,1], 1) )
print( moving_average([2,3,4,5,8,5,4,3,2,1], 2) )
print( moving_average([2,3,4,5,8,5,4,3,2,1], 3) )
输出(parts
作为注释包含):
# [[2], [3], [4], [5], [8], [5], [4], [3], [2], [1]]
[2.0, 3.0, 4.0, 5.0, 8.0, 5.0, 4.0, 3.0, 2.0, 1.0]
# [None, [2, 3], [3, 4], [4, 5], [5, 8], [8, 5], [5, 4], [4, 3], [3, 2], [2, 1]]
[None, 2.5, 3.5, 4.5, 6.5, 6.5, 4.5, 3.5, 2.5, 1.5]
# [None, None, [2, 3, 4], [3, 4, 5], [4, 5, 8], [5, 8, 5], [8, 5, 4],
# [5, 4, 3], [4, 3, 2], [3, 2, 1]]
[None, None, 3.0, 4.0, 5.666666666666667, 6.0, 5.666666666666667, 4.0, 3.0, 2.0]
如果您可以使用标准库,这可能会有所帮助。您真正需要的是在迭代器上滑动 window 。您可以为此使用此功能(这是基于 itertools 食谱中的 grouper
):
from itertools import islice
def window(iterable, n=2):
# window('123', 2) --> '12' '23'
args = [islice(iterable, i, None) for i in range(n)]
return zip(*args)
对于平均值,您可以使用 statistics.mean
。 paddig 部分可以简单地通过添加带有 [None] * (n - 1)
:
的平均列表来实现
from statistics import mean
def moving_average(prices, n):
avgs = [mean(w) for w in window(prices, n)]
padding = [None] * (n - 1)
return padding + avgs
示例用法:
>>> moving_average([2,3,4,5,8,5,4,3,2,1], 3)
[None, None, 3, 4, 5.666666666666667, 6, 5.666666666666667, 4, 3, 2]
>>> moving_average([1, 2, 3], 3)
[None, None, 2]
>>> moving_average([1, 2, 3], 1)
[1, 2, 3]
>>> moving_average([5, 10, 0], 2)
[None, 7.5, 5]
我很难在我的函数中实现移动平均公式。 我花了很长时间才找到代码所在的位置。
有没有我可以去的图书馆?
输入:
ma([2,3,4,3,2,6,9,3,2,1], 4)
预期输出:
[None, None, None, 3.0, 3.0, 3.75, 5.0, 5.0, 5.0, 3.75]
我的输出:
[None, None, 0.0, 3.0, 3.75, 5.0, 5.0, None, None, None]
我 运行 遇到的问题是我的结果的中间部分是正确的,但其余部分是个谜。
- 为什么列表中的最后三个值 return None?
def ma(价格, n):
ma = []
sums = []
s = 0
ave = 0
for idx, i in enumerate(prices):
s += i
sums.append(s)
print('idx: ' + str(idx))
print('list of sums ' + str(sums))
#print('sum ' + str(s))
if i >= n+1:
print('sums[idx] ' + str(sums[idx]))
print('sums[idx-n] ' + str(sums[idx-n]))
ave = (sums[idx] - sums[idx-n]) / n
print('ave ' + str(ave))
ma.append(ave)
print('ma ' + str(ma))
else:
m = None
ma.append(m)
print('ma ' + str(ma))
(抱歉所有这些 print
函数调用,但我真的很想找到问题的根源)。
您的代码中还有其他几个逻辑错误。我试图更正它以使其按您的意愿工作。以下只是 for 循环的修改版本。休息保持不变。 added/modified 行用注释
突出显示for idx, i in enumerate(prices):
s += i
sums.append(s)
if idx == n-1: # Added
ave = (sums[idx]) / n # Added
ma.append(ave) # Added
elif idx >= n: # modified
ave = (sums[idx] - sums[idx-n]) / n
ma.append(ave)
else:
ma.append(None) # removed extra variable m
问题是您使用了错误的变量作为索引:
一个主要问题是您使用
if i >= n+1:
您应该使用:
if idx >= n+1:
此外,我添加了一个 if 语句来处理前三个元素的平均值。
现在
moving_average([2,3,4,5,8,5,4,3,2,1], 3)
给出以下输出(您可以稍后四舍五入):
[None, None, 3.0, 4.0, 5.666666666666667, 6.0, 5.666666666666667, 4.0, 3.0, 2.0]
您的程序返回 9-9 / 3 = 0
的原因是负索引。当 idx
是 2
时,sums[idx-n]
表示 sums[-1]
,它指向列表的最后一项 9
。 Understanding Python's slice notation 可以帮助解释这一点。
您还可以使用列表切片巧妙地对输入列表进行分区并计算列表分区的平均值来解决此问题:
def moving_average(data,window):
"""The partitions begin with window-1 None. Then follow partial lists, containing
window-sized elements. We do this only up to len(data)-window+1 as the following
partitions would have less then window elements."""
parts = [None]*(window-1) + [ data[i:i+window] for i in range(len(data)-window+1)]
# The None's The sliding window of window elements
# we return None if the value is None else we calc the avg
return [ sum(x)/window if x else None for x in parts]
print( moving_average([2,3,4,5,8,5,4,3,2,1], 1) )
print( moving_average([2,3,4,5,8,5,4,3,2,1], 2) )
print( moving_average([2,3,4,5,8,5,4,3,2,1], 3) )
输出(parts
作为注释包含):
# [[2], [3], [4], [5], [8], [5], [4], [3], [2], [1]]
[2.0, 3.0, 4.0, 5.0, 8.0, 5.0, 4.0, 3.0, 2.0, 1.0]
# [None, [2, 3], [3, 4], [4, 5], [5, 8], [8, 5], [5, 4], [4, 3], [3, 2], [2, 1]]
[None, 2.5, 3.5, 4.5, 6.5, 6.5, 4.5, 3.5, 2.5, 1.5]
# [None, None, [2, 3, 4], [3, 4, 5], [4, 5, 8], [5, 8, 5], [8, 5, 4],
# [5, 4, 3], [4, 3, 2], [3, 2, 1]]
[None, None, 3.0, 4.0, 5.666666666666667, 6.0, 5.666666666666667, 4.0, 3.0, 2.0]
如果您可以使用标准库,这可能会有所帮助。您真正需要的是在迭代器上滑动 window 。您可以为此使用此功能(这是基于 itertools 食谱中的 grouper
):
from itertools import islice
def window(iterable, n=2):
# window('123', 2) --> '12' '23'
args = [islice(iterable, i, None) for i in range(n)]
return zip(*args)
对于平均值,您可以使用 statistics.mean
。 paddig 部分可以简单地通过添加带有 [None] * (n - 1)
:
from statistics import mean
def moving_average(prices, n):
avgs = [mean(w) for w in window(prices, n)]
padding = [None] * (n - 1)
return padding + avgs
示例用法:
>>> moving_average([2,3,4,5,8,5,4,3,2,1], 3)
[None, None, 3, 4, 5.666666666666667, 6, 5.666666666666667, 4, 3, 2]
>>> moving_average([1, 2, 3], 3)
[None, None, 2]
>>> moving_average([1, 2, 3], 1)
[1, 2, 3]
>>> moving_average([5, 10, 0], 2)
[None, 7.5, 5]