Python 从不同长度的滚动窗口求和
我试图使用不同长度的滚动窗口从列表的一部分中找到一个特定的总和。首先,我创建了一个基本的数字列表,然后尝试对生成的一些滚动窗口求和。不幸的是,这似乎不可能做到Python 从不同长度的滚动窗口求和,python,list,sum,Python,List,Sum,我试图使用不同长度的滚动窗口从列表的一部分中找到一个特定的总和。首先,我创建了一个基本的数字列表,然后尝试对生成的一些滚动窗口求和。不幸的是,这似乎不可能做到 foo = [] for x in range (1, 200): foo.append(x) def subsequences(iterable, length): return [iterable[i: i + length] for i in xrange(len(iterable) - length + 1)
foo = []
for x in range (1, 200):
foo.append(x)
def subsequences(iterable, length):
return [iterable[i: i + length] for i in xrange(len(iterable) - length + 1)]
for i in range (1, len(foo)):
print sum(subsequences(foo, i))
我收到的错误是:
TypeError:不支持+:“int”和“list”的操作数类型
有没有办法生成每个子序列并求和?检查
子序列()
的输出会发现问题:您试图将一系列列表添加到一起,以实现每个列表中包含的整数值之和
print(subsequences(foo, i))
# [[1], [2], [3], [4], [5], [6], [7], [8] ...]
这不是Python内置的sum
的设计目的,但如果使用Numpy的sum
,此操作将起作用:
import numpy as np
# ...
for i in range (1, len(foo)):
print (np.sum(subsequences(foo, i)))
输出:
19900
39600
59100
78400
97500
116400
...
或者,在应用
sum
之前,您可以提取每个列表中的值,但使用Numpy可以让您的代码保持原样,只需添加np即可。您只需对子序列求和:
[sum(subsequence) for subsequence in subsequences(foo, i)]
当您想对数字求和时,您正在尝试对列表求和。如果您运行以下简单的操作:
>>> print(sum([[1], [2]]))
.....
TypeError: unsupported operand type(s) for +: 'int' and 'list'
您将复制您的TypeError
,这是当前程序的行为
要解决这个问题,只需分解问题
首先查看一次迭代的每个子序列,例如2
:
print([x for x in subsequence(foo, 2)])
# [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11], ......]
然后将每个子序列和:
print([sum(x) for x in subsequences(foo, 2)])
# [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, ......]
然后将此列表相加:
print(sum(sum(x) for x in subsequences(foo, 2)))
# 39600
然后,您的最终for循环将在i
的所有迭代中正常运行:
for i in range (1, len(foo)):
print(sum(sum(x) for x in subsequences(foo, i)))
其行为正确:
19900
39600
59100
78400
97500
116400
135100
153600
171900
190000
207900
225600
243100
......
您可以使用map
将sum
向下推列表嵌套一级;例如:
map(sum, subsequences(foo, 4))
# [10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, ...
一种更有效的方法是首先计算累积和,然后在适当的偏移量处取成对差。您似乎在使用Python2,这很遗憾,因为Python3有一个累积函数。在python 2上,我们需要构建自己的:
def partialsums(a):
def runner(a):
runner.tot += a
return runner.tot
runner.tot = 0
return [0] + [runner(i) for i in a]
ps = partialsums(foo)
现在,您只需执行以下操作:
[r-l for r, l in zip(ps[4:], ps[:-4])]
# [10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, ...
[r-l for r, l in zip(ps[100:], ps[:-100])]
# [5050, 5150, 5250, 5350, 5450, 5550, 5650, 5750, 5850, 5950, 6050, ...
最后一个示例使用直接法进行的算术运算略低于10000次,而使用差分法进行的算术运算仅为300次。在这300次运算中,200次只需执行一次,就可以用于其他窗口长度。但是。。。然后你必须安装numpy@Ben如果您有pip
@RoadRunner,那么这很容易。上次我尝试时遇到了依赖性问题。但是,即使它变得非常琐碎,我也不认为为numpy.sum
安装整个东西是值得的。就我的观点而言,无论如何安装它都有合理的理由。