繁体   English   中英

在大型1维NumPy数组中切片模式

[英]Slicing a pattern in a large 1-d NumPy array

我有一个1维数组,其中的肠腔中有一个模式。 我举一个例子。 在数组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分成三个1-d数组。 所以所需的输出

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数组,因为我知道重复的次数(示例arr中为= arr = 2),然后使用索引获取所有第一个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]))

但是我有兴趣知道一种使用某种掩膜切片 而不需要首先转换为二维数组的有效替代解决方案。

根据要求使用图案的遮罩(并假设arr长度是遮罩长度的精确倍数):

mask1 = [True]*4 + [False]*10
mask2 = [False]*4 + [True]*4 + [False]*6
mask3 = [False]*8 + [True]*6

然后,您可以通过执行以下操作直接获得所需的数组:

n_masks = (len(arr) // len(mask1))
arr1 = arr[mask1 * n_masks]
arr2 = arr[mask2 * n_masks]
arr3 = arr[mask3 * n_masks]

您可以直接访问索引

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)

您还可以构建遮罩:

# if you know where your indices are, otherwise use a formula
mask = np.zeros((3, 2, 14), dtype=bool)
mask[0,:, 0:4] = True
mask[1,:, 4:8] = True
mask[2,:, 8:] = True

arr1, arr2, arr3 = (arr[m.flatten()] for m in mask)
print (arr1, arr2, arr3)

我们可以简单地重塑为2D (记住重塑会创建一个视图,并且内存开销为零,因此在运行时实际上是空闲的),而cols的数量与模式lenth相同(在示例情况下为14)。 然后,对第一个数组输出slice出前4个条目,对第二个slice出下4个,最后一个slice第8个col。

由于我们需要扁平化的输出,因此可以使用.ravel()

因此-

In [44]: a2d = arr.reshape(-1,14) # 2d view into arr
    ...: arr1,arr2,arr3 = a2d[:,:4].ravel(),a2d[:,4:8].ravel(),a2d[:,8:].ravel()

In [45]: arr1
Out[45]: array([1, 2, 3, 4, 6, 5, 3, 2])

In [46]: arr2
Out[46]: array([11, 12, 13, 14, 21, 82, 53, 34])

In [47]: arr3
Out[47]: array([111, 123, 132, 145, 176, 129, 121, 133, 139, 165, 186, 119])

现在,说我们对2D数组输出没问题,然后-

In [48]: arr1,arr2,arr3 = a2d[:,:4],a2d[:,4:8],a2d[:,8:]

In [49]: arr1
Out[49]: 
array([[1, 2, 3, 4],
       [6, 5, 3, 2]])

In [50]: arr2
Out[50]: 
array([[11, 12, 13, 14],
       [21, 82, 53, 34]])

In [51]: arr3
Out[51]: 
array([[111, 123, 132, 145, 176, 129],
       [121, 133, 139, 165, 186, 119]])

那么,为什么要这样做呢? 因为它是原始输入arr的视图,因此如前所述,其内存开销为零,实际上是空闲的-

In [52]: np.shares_memory(arr,arr1)
Out[52]: True

对于其他两个数组,依此类推。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM