[英]numpy array slicing, why sometimes 2-d array and sometimes 1-d array
[英]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.