我希望从numpy数组中获得索引列表(或数组)的结果,其形式为:(len(索引),(一个索引操作的形状))。
有没有办法直接使用索引列表,而不使用for循环,就像我在mininal示例中使用的那样,如下所示?
c = np.random.randint(0, 5, size=(4, 5))
indices = [[0, slice(0, 4)], [1, slice(0, 4)], [1, slice(0, 4)], [2, slice(0, 4)]]
# desired result using a for loop
res = []
for idx in indices:
res.append(c[idx])应该注意的是,索引列表并不代表我的问题,它只是一个例子,通常它是在运行时生成的。但是,每个索引操作都返回相同的形状
发布于 2015-09-04 16:29:38
看起来你基本上是从2D输入数组的开头开始切片,直到2 rows和4 columns,然后拆分每一行。您可以使用c[:2,:4]进行切片,然后使用np.vsplit拆分行,从而获得一个单行解决方案,如下所示-
res_out = np.vsplit(c[:2,:4],2)示例运行-
In [10]: c
Out[10]:
array([[0, 2, 5, 1, 0],
[1, 5, 5, 0, 3],
[0, 1, 0, 6, 6],
[2, 6, 2, 3, 3]])
In [11]: indices
Out[11]: [[0, slice(0, 4, None)], [1, slice(0, 4, None)]]
In [12]: # desired result using a for loop
...: res = []
...: for idx in indices:
...: res.append(c[idx])
...:
In [13]: res
Out[13]: [array([0, 2, 5, 1]), array([1, 5, 5, 0])]
In [14]: np.vsplit(c[:2,:4],2)
Out[14]: [array([[0, 2, 5, 1]]), array([[1, 5, 5, 0]])]请注意,np.vsplit的输出将是二维数组的列表,而不是问题中发布的代码中的一维数组列表。
发布于 2015-09-05 01:22:10
您的示例可以重写为列表理解:
In [121]: [c[idx] for idx in indices]
Out[121]:
[array([4, 2, 1, 2]),
array([3, 2, 2, 3]),
array([3, 2, 2, 3]),
array([0, 3, 4, 4])]它可以变成一个漂亮的二维数组:
In [122]: np.array([c[idx] for idx in indices])
Out[122]:
array([[4, 2, 1, 2],
[3, 2, 2, 3],
[3, 2, 2, 3],
[0, 3, 4, 4]])在这里,np.array()是一种连接形式,沿着新的轴连接数组。
由于第2个索引对于所有行都是相同的(slice(4)),因此此索引也适用:
In [123]: c[[0,1,1,2],slice(4)] # or [...,:4]
Out[123]:
array([[4, 2, 1, 2],
[3, 2, 2, 3],
[3, 2, 2, 3],
[0, 3, 4, 4]])在第一轴上重复是不成问题的。在第二个不同的切片需要更多的操作。除了这种特殊的:4情况,您必须将切片转换为范围。没有办法用多个切片来索引一个维度。
切片的长度相同,但'start‘值不同的情况与https://stackoverflow.com/a/28007256/901925 access-multiple-elements-of-an-array中讨论的情况类似。
In [135]: c.flat[[i*c.shape[1]+np.arange(j.start,j.stop) for i,j in indices]]
Out[135]:
array([[4, 2, 1, 2],
[3, 2, 2, 3],
[3, 2, 2, 3],
[0, 3, 4, 4]])我以这种方式生成的索引是:
In [136]: [i*c.shape[1]+np.arange(j.start,j.stop) for i,j in indices]
Out[136]:
[array([0, 1, 2, 3]),
array([5, 6, 7, 8]),
array([5, 6, 7, 8]),
array([10, 11, 12, 13])]如果indices有点不规则,它工作得很好:indices1 = [[0, slice(0, 3)], [1, slice(2, 5)], [1, slice(1, 4)], [2, slice(0, 3)]]
我之前的回答看了一些其他的索引方式。但是,即使考虑到生成索引数组所需的计算,在扁平数组上进行索引通常也是最快的。
如果片段的长度不同,那么您就不得不生成一个数组列表,或者生成这样一个列表的hstack:
In [158]: indices2 = [[0, slice(0, 2)], [1, slice(2, 5)],
[1, slice(0, 4)], [2, slice(0, 5)]]
In [159]: c.flat[np.hstack([i*c.shape[1]+np.arange(j.start,j.stop)
for i,j in indices2])]
Out[159]: array([4, 2, 2, 3, 1, 3, 2, 2, 3, 0, 3, 4, 4, 3])
In [160]: [c.flat[i*c.shape[1]+np.arange(j.start,j.stop)] for i,j in indices2]
Out[160]: [array([4, 2]), array([2, 3, 1]), array([3, 2, 2, 3]),
array([0, 3, 4, 4, 3])]
In [161]: np.hstack(_)
Out[161]: array([4, 2, 2, 3, 1, 3, 2, 2, 3, 0, 3, 4, 4, 3])更多关于不同但长度相等的切片:
In [190]: indices1 = [[0, slice(0, 3)], [1, slice(2, 5)], [1, slice(1, 4)], [2, slice(0, 3)]]
In [191]: c.flat[[i*c.shape[1]+np.arange(j.start,j.stop) for i,j in indices1]]Out[191]:
array([[4, 2, 1],
[2, 3, 1],
[2, 2, 3],
[0, 3, 4]])
In [193]: rows = [[i] for i,j in indices1]
In [200]: cols=[np.arange(j.start,j.stop) for i,j in indices1]
In [201]: c[rows,cols]
Out[201]:
array([[4, 2, 1],
[2, 3, 1],
[2, 2, 3],
[0, 3, 4]])在这种情况下,rows是可以用cols广播的垂直列表。
https://stackoverflow.com/questions/32393217
复制相似问题