以相反的顺序在python中运行项目列表的平均值

时间:2013-08-13 04:04:30

标签: python list average

我需要在一维列表中找到项目的平均值:   例如:L = [123,678,234,256,789,-----]                首先,我需要从列表中的最后一项开始获得运行平均值。因此,提供如下结果列表:reslist = [416,489.25,426.33,522.5,789 ---]。 Plz可以任何人在python中建议一个简单的代码,这样做会有所帮助..

2 个答案:

答案 0 :(得分:2)

因此,对于每个索引i,您需要L[i]L[-1]的平均值,对吗?

首先,让我们编写一个简单的average函数:

def average(values):
    return sum(values) / len(values)

现在,我们可以将描述翻译成代码:

running_averages = [average(L[i:]) for i in range(len(L))]

你似乎也希望以某种未指明的方式对事物进行舍入(489.25舍入为489,但522.5为522.5);如果你可以描述规则,我可以展示如何实现它,但我不能从你的例子中猜出规则。


当然,如果L很长,这个效率不高,因为它会增加len(L)**2 / 2次。有没有办法我们可以在len(L)中做到这一点?当然,它只是有点复杂。例如:

partial_sums = itertools.accumulate(reversed(L))
averages = [value/(i+1) for i, value in enumerate(partial_sums)]
averages.reverse()

第一步和最后一步很简单:只需在开头然后结束时反转列表即可。但其余的呢?

首先,accumulate只接受任何迭代,并返回带累积和的迭代器。因此它会为您i[0],然后i[0] + i[1],然后i[0] + i[1] + i[2],等等。但是,因为它会记住最后的部分和,所以每个步骤只需要一次添加。换句话说,它会为您提供0 + i[0],然后是result[0] + i[1],然后是result[1] + i[2]。如果你想看看它是如何工作的(或者如果你使用的是没有accumulate的旧版Python),那么链接的文档将展示你如何自己构建它。

然后,我们只是将每个部分和除以索引(+ 1,因为Python索引从0开始)以获得运行平均值。列表理解应该是显而易见的;如果你不知道enumerate函数,那就是唯一聪明的一点。


这不是唯一的方法。您也可以使用functools.reduce或显式循环,或者通过累加器传递或者一个天真的递归函数构建尾递归函数,或者......尝试编写与您一样多的函数可能是一个很好的练习能够。可能只有一种显而易见的方法可以做到这一点,但有时候直到你尝试一些方法并不明显哪一种是明显的方法。 :)


另一种方法是使用numpy。 rogaos删除了他太简单的答案,但这是一个开始。

首先,简单的部分:反转列表,并将其塞进一个numpy数组:

a = np.array(reversed(L))

现在,诀窍是写一个矢量化的运行总和。好吧,numpy带有convolve,并且与N次运行进行卷积会给你一个N + M-1窗口的总和。那么,如果窗口和整个数组一样宽,会发生什么?我们得到的窗口总和几乎是我们需要的两倍,其中第一个len(L)值是运行总和。所以:

running_sums = np.convolve(a, np.ones(len(L)))[:len(L)]

然后我们只是按指数划分,就像在itertools版本中一样:

running_means = running_sums / np.arange(1, len(L)+1)

现在我们只需将其反转并将其转回列表:

reslist = list(reversed(running_means))

当然,在现实生活中,你可能希望Lreslist也是numpy数组,这使得它更简单。

无论如何,使用numpy的好处是一些操作更简单(请注意我是如何将一个数组分成另一个数组而不是编写列表解析),并且通常快约10倍(所有循环和算术运算都需要放在C中,或偶尔使用C ++或Fortran,而不是Python)。缺点是你必须弄清楚如何将每个循环转变为合理的数学运算。 (如果你不知道convolve做了什么,你就不会想到在这里使用它。)

答案 1 :(得分:0)

这是一个使用递归的解决方案:

def runningMean(seq, n=0, total=0):
    if not seq:
        return []
    total = total+seq[-1]
    return runningMean(seq[:-1], n=n+1, total=total) + [total/float(n+1)]

<强>样本

print(runningMean([123,678,234,256,789]))

输出:

[416.0, 489.25, 426.3333333333333, 522.5, 789.0]