首页 > 解决方案 > 在大型一维 NumPy 数组中切片模式

问题描述

我有一个一维数组,其中我有一个图案。我举个例子。在数组arr中,我有前 4 个单位数字的输入,接下来的 4 个两位数字的输入,然后是接下来的 6 个数字的 3 数字输入。(这个单,双,三位数的东西只是为了突出模式。实际的数组具有相似值的浮点数)。示例一维数组如下所示:

import numpy as np
arr = np.array([1, 2, 3, 4, 11, 12, 13, 14, 111, 123, 132, 145, 176, 129, 
                6, 5, 3, 2, 21, 82, 53, 34, 121, 133, 139, 165, 186, 119])

现在,一个完整的模式总共有 4+4+6 = 14 个输入。这个模式(或重复单元)重复了几十万次,所以我的数组的长度是 14 的倍数(在arr上面的例子中是 14 * 2 = 28)。

问题:

我想提取所有一位数字输入(一个重复单元的前 4 个数字)、所有两位数字输入(一个重复单元的下 4 个数字)和所有三位数字输入(一个重复单元的下 6 个数字)。

这样我想把我的大arr拆分成三个一维数组。所以想要的输出

arr1 = array([1, 2, 3, 4, 6, 5, 3, 2])
arr2 = array([11, 12, 13, 14, 21, 82, 53, 34])
arr3 = array([111, 123, 132, 145, 176, 129, 121, 133, 139, 165, 186, 119])

我的想法

一种方法可能是将其简单地reshape转换为 2d 数组,因为我知道重复次数(示例中为 = 28/14 = 2 arr),然后使用索引来获取 4、4 和 6 的所有第一个块,然后concatenate

arr = arr.reshape(2, 14)

然后使用切片将块获取为

arr1 = np.concatenate(arr[:, 0:4])
arr2 = np.concatenate(arr[:, 4:8])
arr3 = np.concatenate(arr[:, 8:])
print (arr1, arr2, arr3)

# array([1, 2, 3, 4, 6, 5, 3, 2]),
# array([11, 12, 13, 14, 21, 82, 53, 34]),
# array([111, 123, 132, 145, 176, 129, 121, 133, 139, 165, 186, 119]))

但我有兴趣了解一种替代且有效的解决方案,该解决方案使用某种屏蔽切片 而不首先转换为二维数组。

标签: pythonnumpyindexingslice

解决方案


您可以直接访问索引

import numpy as np
arr = np.array([1, 2, 3, 4, 11, 12, 13, 14, 111, 123, 132, 145, 176, 129,
                6, 5, 3, 2, 21, 82, 53, 34, 121, 133, 139, 165, 186, 119])

run_length = 14
repetitions = 2

indices1 = [run_length * i + j for i in range(repetitions) for j in range(4)]
arr1 = arr[indices1]

indices2 = [run_length * i + j for i in range(repetitions) for j in range(4, 8)]
arr2 = arr[indices2]

indices3 = [run_length * i + j for i in range(repetitions) for j in range(8, 14)]
arr3 = arr[indices3]

print(arr1)
print(arr2)
print(arr3)

输出

[1 2 3 4 6 5 3 2]
[11 12 13 14 21 82 53 34]
[111 123 132 145 176 129 121 133 139 165 186 119]

您可以将所有内容放在这样的函数中:

import numpy as np
arr = np.array([1, 2, 3, 4, 11, 12, 13, 14, 111, 123, 132, 145, 176, 129,
                6, 5, 3, 2, 21, 82, 53, 34, 121, 133, 139, 165, 186, 119])


def extract(arr, run_length, repetitions, pattern_lengths):
    chunks = [0] + np.cumsum(pattern_lengths).tolist()

    for start, end in zip(chunks, chunks[1:]):
        indices = [run_length * i + j for i in range(repetitions) for j in range(start, end)]
        yield arr[indices]


arr1, arr2, arr3 = list(extract(arr, 14, 2, [4, 4, 6]))

print(arr1)
print(arr2)
print(arr3)

推荐阅读