计算移动平均线

时间:2018-09-16 14:40:07

标签: python average data-science 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]

我遇到的问题是,结果的中间部分是正确的,但其余部分仍然是个谜。

  1. 为什么列表中的最后三个值都返回None?

def ma(prices,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函数调用都很抱歉,但是我真的很想找到问题的根源)。

4 个答案:

答案 0 :(得分:2)

您的代码中还有其他逻辑错误。我试图对其进行纠正以使其按需工作。以下仅是for循环的修改版本。休息保持不变。添加/修改的行以注释突出显示

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]

答案 1 :(得分:1)

如果可以使用标准库,则可能会有所帮助。您真正需要的是迭代器上的滑动窗口。您可以为此使用此功能(该功能基于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]

答案 2 :(得分:0)

程序返回stateToProps的原因是负索引。当var INPUT = 'INPUT'; var setInput = (val = '') => ({ type: INPUT, payload: val }) var modelA = (state = {test1: '', test2: false, inputVal: ''}, action) => { switch (action.type) { case this.INPUT: state.inputVal = action.payload; return state default: return state } } var modelB = (state = {test1: '', content: ''}, action) => { switch (action.type) { default: return state } } var stateToProps = state => { return { storeValue: state.modelA.inputVal } } var dispatchToProps = dispatch => { return { setStoreVal: (val) => { dispatch(setInput(val)) } } } class App extends React.Component { constructor(props) { super(props); this.store = Redux.createStore(Redux.combineReducers({modelA, modelB})); } render() { return e( ReactRedux.Provider, {store:this.store}, e('div', null, "App", e(ReactRedux.connect(stateToProps, dispatchToProps)(Whatever), null) ) ); } } class Whatever extends React.Component { constructor(props) { super(props); this.state = {val:0} this.listener = this.listener.bind(this); } listener(evt) { this.props.setStoreVal(evt.currentTarget.value); this.setState({val:evt.currentTarget.value}); } render() { return e( 'div', null, e('p', null, this.props.storeValue), e('input', {onChange:this.listener, val:this.state.val}) ); } } 9-9 / 3 = 0时,idx在说2,它指向列表的最后一项,sums[idx-n]Understanding Python's slice notation可以帮助解释这一点。

答案 3 :(得分:0)

您还可以使用列表切片来解决此问题,以对输入列表进行智能分区并计算列表分区的平均值:

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]