Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python3中计算移动平均线?_Python_Python 3.x - Fatal编程技术网

如何在Python3中计算移动平均线?

如何在Python3中计算移动平均线?,python,python-3.x,Python,Python 3.x,假设我有一个列表: y = ['1', '2', '3', '4','5','6','7','8','9','10'] 我想创建一个计算n天移动平均值的函数。 因此,如果n为5,我希望我的代码计算前1-5,将其相加,找到平均值,即3.0,然后继续到2-6,计算平均值,即4.0,然后是3-7,4-8,5-9,6-10 我不想计算前n-1天,所以从第n天开始,它将计算前几天 def moving_average(x:'list of prices', n): for num in rang

假设我有一个列表:

y = ['1', '2', '3', '4','5','6','7','8','9','10']
我想创建一个计算n天移动平均值的函数。 因此,如果
n
为5,我希望我的代码计算前1-5,将其相加,找到平均值,即3.0,然后继续到2-6,计算平均值,即4.0,然后是3-7,4-8,5-9,6-10

我不想计算前n-1天,所以从第n天开始,它将计算前几天

def moving_average(x:'list of prices', n):
    for num in range(len(x)+1):
        print(x[num-n:num])
这似乎打印出了我想要的:

[]
[]
[]
[]
[]

['1', '2', '3', '4', '5']

['2', '3', '4', '5', '6']

['3', '4', '5', '6', '7']

['4', '5', '6', '7', '8']

['5', '6', '7', '8', '9']

['6', '7', '8', '9', '10']

然而,我不知道如何计算这些列表中的数字。有什么想法吗?

使用
sum
map
函数

print(sum(map(int, x[num-n:num])))
Python 3中的
map
函数基本上是此函数的惰性版本:

[int(i) for i in x[num-n:num]]

我相信您可以猜到sum函数的作用。

旧版Python文档中有一个很棒的滑动窗口生成器,它具有:

使用移动平均线很简单:

from __future__ import division  # For Python 2

def moving_averages(values, size):
    for selection in window(values, size):
        yield sum(selection) / size
针对您的输入运行此操作(将字符串映射为整数)将提供:

要返回“不完整”集合的第一次迭代,只需稍微扩展移动平均值函数即可:

def moving_averages(values, size):
    for _ in range(size - 1):
        yield None
    for selection in window(values, size):
        yield sum(selection) / size

避免重新计算中间和的方法

list=range(0,12)
def runs(v):
 global runningsum
 runningsum+=v
 return(runningsum)
runningsum=0
runsumlist=[ runs(v) for v in list ]
result = [ (runsumlist[k] - runsumlist[k-5])/5 for k in range(0,len(list)+1)]
打印结果

[2,3,4,5,6,7,8,9]

使其运行(int(v))。。然后。。repr(runsumlist[k]-runsumlist[k-5])/5) 如果你想随身携带数字和字符串


不带全局变量的Alt:

list = [float[x] for x in range(0,12)]
nave = 5
movingave = sum(list[:nave]/nave)
for i in range(len(list)-nave):movingave.append(movingave[-1]+(list[i+nave]-list[i])/nave)
print movingave 
即使输入值是整数,也要确保进行浮点运算

[2.0,3.0,4.0,5.0,6.0,7.0,8.0,9,0]
虽然我喜欢这个,像george一样,我想知道如果使用运行求和而不是对几乎相同的数字反复应用
sum()
,这是否会更快

另外,在提升阶段将
None
值作为默认值的想法也很有趣。事实上,移动平均线可能有很多不同的情况。让我们将平均值的计算分为三个阶段:

  • 爬升:在当前迭代计数<窗口大小的情况下开始迭代
  • 稳步进展:我们有准确的窗口大小元素数量,可用于计算正常
    平均值:=sum(x[迭代\u计数器-窗口\u大小:迭代\u计数器])/window\u大小
  • 渐变:在输入数据的末尾,我们可以返回另一个
    窗口大小-1
    平均值
  • 这里有一个函数可以接受

    • 任意iterables(生成器很好)作为数据输入
    • 任意窗口大小>=1
    • 在上升/下降阶段打开/关闭值生成的参数
    • 这些阶段的回调函数用于控制值的生成方式。这可用于持续提供默认值(例如,
      None
      )或提供部分平均值
    代码如下:

    from collections import deque 
    
    def moving_averages(data, size, rampUp=True, rampDown=True):
        """Slide a window of <size> elements over <data> to calc an average
    
        First and last <size-1> iterations when window is not yet completely
        filled with data, or the window empties due to exhausted <data>, the
        average is computed with just the available data (but still divided
        by <size>).
        Set rampUp/rampDown to False in order to not provide any values during
        those start and end <size-1> iterations.
        Set rampUp/rampDown to functions to provide arbitrary partial average
        numbers during those phases. The callback will get the currently
        available input data in a deque. Do not modify that data.
        """
        d = deque()
        running_sum = 0.0
    
        data = iter(data)
        # rampUp
        for count in range(1, size):
            try:
                val = next(data)
            except StopIteration:
                break
            running_sum += val
            d.append(val)
            #print("up: running sum:" + str(running_sum) + "  count: " + str(count) + "  deque: " + str(d))
            if rampUp:
                if callable(rampUp):
                    yield rampUp(d)
                else:
                    yield running_sum / size
    
        # steady
        exhausted_early = True
        for val in data:
            exhausted_early = False
            running_sum += val
            #print("st: running sum:" + str(running_sum) + "  deque: " + str(d))
            yield running_sum / size
            d.append(val)
            running_sum -= d.popleft()
    
        # rampDown
        if rampDown:
            if exhausted_early:
                running_sum -= d.popleft()
            for (count) in range(min(len(d), size-1), 0, -1):
                #print("dn: running sum:" + str(running_sum) + "  deque: " + str(d))
                if callable(rampDown):
                    yield rampDown(d)
                else:
                    yield running_sum / size
                running_sum -= d.popleft()
    
    以及输出:

    Timeit
    --------------------------------------------------------------------------------
    10                 7.242        7.656 
    100                5.816        5.500 
    1000               5.787        5.244 
    10000              5.782        5.180 
    100000             5.746        5.137 
    1000000            5.745        5.198 
    10000000           5.764        5.186 
    
    [None, None, None, None, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
    
    原来的问题现在可以通过此函数调用解决:

    print(list(moving_averages(range(1,11), 5,
                               rampUp=lambda _: None,
                               rampDown=False)))
    
    输出:

    Timeit
    --------------------------------------------------------------------------------
    10                 7.242        7.656 
    100                5.816        5.500 
    1000               5.787        5.244 
    10000              5.782        5.180 
    100000             5.746        5.137 
    1000000            5.745        5.198 
    10000000           5.764        5.186 
    
    [None, None, None, None, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
    

    还有另一个解决方案扩展了
    itertools
    recipe
    pairwise()
    。您可以将其扩展到
    nwise()
    ,它为您提供了滑动窗口(如果iterable是一个生成器,则可以工作):

    iterable
    s的设置成本相对较高,但数据集越长,此成本的影响就越小。这使用了
    sum()
    ,但代码相当优雅:

    Timeit              MP           cfi         *****
    --------------------------------------------------------------------------------
    10                 4.658        4.959        7.351 
    100                5.144        4.070        4.234 
    1000               5.312        4.020        3.977 
    10000              5.317        4.031        3.966 
    100000             5.508        4.115        4.087 
    1000000            5.526        4.263        4.202 
    10000000           5.632        4.326        4.242 
    

    为什么列表中有字符串而不是数字?我希望结果是[none,none,none,none,none,3.0,4.0,5.0,6.0,7.0,8.0]虽然我欣赏你优雅的解决方案,但我还是将它与跟踪运行总和的方法进行了比较,而不是多次重新计算总和。看见如果函数被简化为只回答原始问题,而不允许附加参数,那么这可能会更快。事实上,运行求和算法更快。我已经发布了一个答案来证明你的观点。这里不需要
    全局变量。
    
    def nwise(iterable, n):
        ts = it.tee(iterable, n)
        for c, t in enumerate(ts):
            next(it.islice(t, c, c), None)
        return zip(*ts)
    
    def moving_averages_nw(iterable, n):
        yield from (sum(x)/n for x in nwise(iterable, n))
    
    >>> list(moving_averages_nw(range(1, 11), 5))
    [3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
    
    Timeit              MP           cfi         *****
    --------------------------------------------------------------------------------
    10                 4.658        4.959        7.351 
    100                5.144        4.070        4.234 
    1000               5.312        4.020        3.977 
    10000              5.317        4.031        3.966 
    100000             5.508        4.115        4.087 
    1000000            5.526        4.263        4.202 
    10000000           5.632        4.326        4.242