【问题标题】:Sliding window over numerical sequence数字序列上的滑动窗口
【发布时间】:2017-11-04 10:48:27
【问题描述】:

我正在尝试构建一种滑动窗口方法,该方法将在列表中元素的数字序列上滑动。这一点很重要,我相信这与 SO 中的其他滑动窗口方法不同,后者通常在列表的索引上进行滑动。

我的意思是类似于以下内容。拥有整数列表

li = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

使用window=3step=2,预期输出将是:

[1, 3]
[3, 4, 5]
[5, 6, 7]
[7, 8, 9]
[9, 10, 11]
[11, 12]

我目前的代码:

window = 3
step = 2

last_pos = 0
w_start = 1
w_end = window
next_start = w_start + step
dat = []  # values for window
next_dat = []  # values for the next window

li = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

for e in li:
    ipos = int(e)
    if ipos > last_pos:
        dat.append(ipos)

        if ipos == w_end:  # end of window
            w_start += step
            w_end += step
            print(dat)
            dat = next_dat  # reset window...

        if ipos >= next_start:  # ipos is in the next window
            next_dat.append(ipos)

        if w_start == next_start:  # move next window
            next_start += step
            next_dat = []  # reset next window...
    else:
        raise Exception('List is not sorted')

    last_pos += 1

# the last window if not empty
print(dat) if dat else 'false'

输出是预期的:

[1, 3]
[3, 4, 5]
[5, 6, 7]
[7, 8, 9]
[9, 10, 11]
[11, 12]

但是,除了不太优雅之外,当两个以上的窗口重叠时,此代码似乎会失败。例如,window=5step=2 会产生错误的输出:

[1, 3, 4, 5]
[3, 4, 5, 6, 7]
[6, 7, 8, 9]
[8, 9, 10, 11]
[10, 11, 12]

第一个和第二个窗口还可以,但是从第三个开始,事情变得一团糟。例如,第三个窗口应该从 5 开始并且应该有 5 个元素,而不是 4 个。我的目标是获得以下窗口:

[1, 3, 4, 5]
[3, 4, 5, 6, 7]
[5, 6, 7, 8, 9]
[7, 8, 9, 10, 11]
[9, 10, 11, 12]

关于如何解决此行为的任何想法?

请注意,滑动的不是列表索引,而是列表值本身。我相信这两种方法在列表中缺少某些值的特定情况下是不同的。在上面显示的情况下,列表中的前三个项目是1, 3, 4。我认为迭代索引(window=2step=2)会导致以下输出(但未经测试):

[1, 3]
[4]

而我想做的是迭代列表的值,以便生成的窗口是:

[1]
[3, 4]

因此,第一个窗口中缺少值 2,因为它不在原始列表中。

虽然这里最后用一个列表说明了这一点,但我还是想从一个几乎无法放入内存的大文件中读取这些内容。

【问题讨论】:

  • if ipos > last_pos:改成if ipos >= last_pos:
  • 对不起,我弄糊涂了,把ipos == w_end改成ipos > w_end
  • 啊,差不多了。这修复了窗口的启动,但随后与其他所有内容混淆。
  • 您可以通过指出可能的输入和可能的输出来更好地解释您的要求
  • @eyllanesc 抱歉,但我相信帖子中对此进行了解释。我列出了输入,为了举例说明,列表 li = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 并且所需的输出已经存在。有什么可以用来说明问题的吗?

标签: python python-3.x sliding-window


【解决方案1】:

问题中代码的问题在于不确定您需要事先跟踪多少个窗口。 此任务的最佳方法可能是只为窗口使用一个列表,然后复制与下一个窗口重叠的那些值,依此类推。

以下代码适用于我测试的所有窗口:

window = 3
step = 2

last_pos = 0
w_start = 1
w_end = window
dat = []  # values for window
next_dat = []  # values for the next window

li = [1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

for e in li:
    ipos = int(e)
    if ipos > last_pos:

        if ipos > w_end:  # end of window
            print(dat)
            w_start += step
            w_end += step

            if step == window:  # non-overlapping
                next_dat = []  # reset next window...
            else:
                next_dat = [x for x in dat if x >= (w_start)]

            dat = next_dat  # reset window...

        dat.append(ipos)
    else:
        raise Exception('List is not sorted')

    last_pos += 1

# the last window if not empty
print(dat) if dat else 'false'

(窗口=3 和步骤=2)

[1, 3]
[3, 4, 5]
[5, 6, 7]
[7, 8, 9]
[9, 10, 11]
[11, 12]

(窗口=2 和步骤=2)

[1]
[3, 4]
[5, 6]
[7, 8]
[9, 10]
[11, 12]

(窗口=5 和步骤=2)

[1, 3, 4, 5]
[3, 4, 5, 6, 7]
[5, 6, 7, 8, 9]
[7, 8, 9, 10, 11]
[9, 10, 11, 12]

再一次,我认为这段代码不是很优雅,但它可以完成工作,所以我会将此答案标记为已接受。但是,我仍然愿意对此代码进行任何改进/建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2020-10-10
    • 2021-06-14
    • 2017-03-17
    • 2021-08-27
    相关资源
    最近更新 更多