簡體   English   中英

來自不同長度滾動窗口的總和

[英]Sum from rolling window of varying lengths

我正在嘗試使用各種長度的滾動窗口從列表的一部分中查找特定的總和。 首先,我創建了一個基本的數字列表,然后嘗試總結一些生成的滾動窗口。 不幸的是,似乎無法做到這一點。

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”

有什么方法可以生成每個子序列並將它們相加嗎?

檢查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. 而且你很好。

您只需要對子序列求和:

[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, ...

一種更有效的方法是先計算累加和,然后在適當的偏移量處獲取成對差。 您似乎對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, ...

與直接方法相比,使用差分方法僅需300次,而使用差分方法僅需300次,而最后300個示例中的200次僅需執行一次,即可用於其他窗口長度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM