从不同长度的滚动窗口求和

时间:2017-12-10 01:45:44

标签: 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)]

for i in range (1, len(foo)):
    print sum(subsequences(foo, i))

我收到的错误是:

TypeError:+:'int'和'list'的不支持的操作数类型

有没有办法可以生成每个子序列并对它们求和?

4 个答案:

答案 0 :(得分:2)

检查subsequences()的输出会显示问题:您正在尝试将一系列列表添加到一起,以实现每个列表中包含的整数值的总和。

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.就可以了。

答案 1 :(得分:1)

您只需要对子序列求和:

[sum(subsequence) for subsequence in subsequences(foo, i)]

答案 2 :(得分:1)

当您想要对数字求和时,您尝试对列表求和。如果你运行的东西很简单:

>>> 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

对于i

的所有迭代,您的最终for循环将正常运行
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
......

答案 3 :(得分:1)

您可以使用map来推送sum向下一级列表嵌套&#34 ;;例如:

map(sum, subsequences(foo, 4))

# [10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, ...

更有效的方法是首先计算累积和,然后在合适的偏移处采用成对差异。你似乎在python 2上,这是一个遗憾,因为python 3有一个累积函数。在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, ...

最后一个示例使用直接方法略低于10,000次算术运算,而使用差分法仅使用300次算法运算,而这些300,200只需要执行一次,并且可以重复用于其他窗口长度。