【问题标题】:How to write a sliding window algorithm that accounts for a step_size of 0?如何编写一个step_size为0的滑动窗口算法?
【发布时间】:2016-03-18 17:59:15
【问题描述】:

我正在处理一个大文本文件,其中包含具有这种格式的 pi 的小数位。注意头部全是数字,没有字符串。

标题格式:Number_of_sequences Total_Pi_Digits File_Version_Number

550 10000 5

*Pi Sequence Part 1
1415926535897932384
*Pi Sequence Part 2
6264338327950288419
*Pi Sequence Part 3
1693993751058209749

我需要制作一个使用三个参数(window_size、step_size 和 last_windowstart)裁剪文件的滑动窗口。 last_windowstart 是最后一个窗口开始的地方。

文件数由 Total_Pi_Digits 除以窗口来确定。

如果文件有 99 个 Total_Pi_Digits,window_size 为 10,step_size 为零,则从 99//10=10 和 99%10 将 9 个窗口留在窗口 11 中总共有 11 个窗口。

lastwindow_start 应该是 90 我猜这个例子。我不确定我是否需要 last_window 启动。

对于每个窗口,将创建一个名为 PiSubsection# 的文件 其中 # 是窗口编号。

对于每个文件,每个窗口都应该有相同的新标题,其中 Number_of_sequences Total_Pi_Digits File_Version_Number 是标题格式。

Number_of_sequences Total_Pi_Digits 将根据 window_size 和 step_size 而改变,但 File_Version_Number 不得改变。

我的问题是我的滑动窗口算法没有考虑到 0 的 step_size 并且它没有产生正确数量的文件。 到目前为止,它产生了两倍的文件,我不知道为什么。

此外,我也不确定是否理解滑动窗口算法中窗口数量的数学运算。

如何修复我的滑动窗口算法以接受 0 的 step_size 并生成适量的输出文件?

    inputFileName = example.txt

    import shlex

    def sliding_window(windows_size, step_size, lastwindow_start):
        for i in xrange(0, lastwindow_start, step_size):
            yield (i, i + windows_size)

    def PiCrop(windows_size, step_size):

    with open(inputFileName, 'r') as input:
        first_line = shlex.split(input.readline().strip())
        PiNumber = int(first_line[1])

        lastwindow_start = PiNumber-(PiNumber%windows_size)
        flags = [False for i in range(lastwindow_start)]

        first_line[1] = str(windows_size * int(first_line[0]))

        first_line = " ".join(first_line)

        for line in input:
            if line.startswith(first_line[0]):
                pass
            elif line.startswith('*'):
                Indiv = line
            else:
                for counter, window in        enumerate(sliding_window(windows_size,step_size,lastwindow_start)):
                    newline = line[window[0]:window[1]]

                    with open('PiSection{}.txt'.format(counter), 'a') as output:
                        if (flags[counter] == False):
                            flags[counter] = True
                            output.write(first_line + '\n')
                        output.write(Indiv)
                        output.write(newline + '\n')

【问题讨论】:

  • 你的滑动窗口的概念和这里描述的一样吗? stackoverflow.com/questions/8269916/… 另外,在我看来,步长必须至少为 1,否则算法将保持在同一索引上?
  • 是的。这就是我感到困惑的地方。问题是它确实创建了正确数量的文件。

标签: python algorithm text range sliding-window


【解决方案1】:

下面的示例代码提供了另一种方法来避免需要进行计算。我认为加载数字文件或之后实际编写“窗口”文件都没有问题,因此我的代码假定它们已加载并生成一个准备写入的数字窗口数组。

根据该结果,您可以像以前一样简单地迭代现在派生的窗口并输出文件,或者您可以深入嵌套数据并根据需要获取单个窗口进行处理。

示例输出如下。让我知道是否需要更多详细信息...

import pprint

# Separated just for easy comparison with the output.
pi_digits = '1415926535' + '8979323846' + '2643383279' + '5028841916' + '9399375105' + '8209749'
total_digits = len(pi_digits)

def splitIntoWindows(digits, window_size):
    result = []
    count = 0
    window = -1
    for digit in digits:
        index = count % window_size
        if index == 0:
            window += 1
            result.append([])
        result[window] += digit
        count += 1
    return result

windows = splitIntoWindows(pi_digits, 10)

print("Split into {} window(s):".format(len(windows)))
pprint.pprint(windows)

示例输出:

Split into 6 window(s):
[['1', '4', '1', '5', '9', '2', '6', '5', '3', '5'],
 ['8', '9', '7', '9', '3', '2', '3', '8', '4', '6'],
 ['2', '6', '4', '3', '3', '8', '3', '2', '7', '9'],
 ['5', '0', '2', '8', '8', '4', '1', '9', '1', '6'],
 ['9', '3', '9', '9', '3', '7', '5', '1', '0', '5'],
 ['8', '2', '0', '9', '7', '4', '9']]

编辑

为了避免我做太多假设,这里有一个 sn-p 来解析加载的数字文件:

# Assumed these are the contents loaded in:
file_contents = '''
550 10000 5

*Pi Sequence Part 1
1415926535897932384
*Pi Sequence Part 2
6264338327950288419
*Pi Sequence Part 3
1693993751058209749
'''

pi_digits = ''
line_num = 0
for line in file_contents.split('\n'):
    line = line.strip()
    if (len(line) > 0) & (line[0:1] != "*"):
        line_num += 1
        if (line_num > 1):
            pi_digits += line

这应该让 pi_digits 可以使用,因此您可以将我上面代码中的 pi_digits 声明替换为这个。

【讨论】:

    【解决方案2】:

    解决方案是将文件存储在一个列表中,然后使用该列表的块和滑动窗口生成器来创建所有迷你文件。

    inputFileName = "sample.txt"
    
    import itertools
    import linecache
    
    def sliding_window(window_size, step_size, lastwindow_start):
        for i in xrange(0, lastwindow_start, step_size):
            yield (i, i + window_size)
        yield (lastwindow_start, total_pi_digits)
    
    def PiCrop(window_size, step_size):
    
        f = open(inputFileName, 'r')
    
        first_line = f.readline().split()
    
        total_pi_digits = int(first_line[0])
    
        lastwindow_start = total_pi_digits-(total_pi_digits%window_size)
    
        lastcounter = (total_pi_digits//window_size)*(window_size/step_size)
    
        flags = [False for i in range(lastcounter)]
    
        first_line[0] = str(window_size)
        second_line = f.readline().split()
        offset = int(round(float(second_line[0].strip('\n'))))
        first_line = " ".join(first_line)
    
        f. close()
    
        with open(inputFileName, 'r') as f:
            header = f.readline()
            data = [line.strip().split(',') for line in f.readlines()]
    
            for counter, window in enumerate(sliding_window(window_size,step_size,lastwindow_start)):
                chunk = data[window[0]:window[1]]
    
                print window
    
                with open('PiCrop_{}.txt'.format(counter), 'w') as output:
    
                    if (flags[counter] == False):
                        flags[counter] = True
    
                        headerline = float(linecache.getline(inputFileName, window[1]+1)) - offset
                        output.write(str(window_size) + " " + str("{0:.4f}".format(headerline)) + " " + 'L' + '\n')
    
                    for item in chunk:
                        newline = str("{0:.4f}".format(float(str(item).translate(None, "[]'"))-offset))
                        output.write(str(newline) + '\n')
    

    【讨论】:

      猜你喜欢
      • 2021-07-01
      • 2019-12-19
      • 2011-05-06
      • 1970-01-01
      • 2010-11-14
      • 2013-03-30
      • 2011-01-13
      • 2015-02-27
      • 2014-03-29
      相关资源
      最近更新 更多