脾气暴躁的索引切片而不会丢失尺寸信息


98

我正在使用numpy,并希望在不丢失维度信息的情况下对行进行索引。

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10,:]
xslice.shape   # >> (10,)  

在此示例中,xslice现在为1维,但我希望它为(1,10)。在R中,我将使用X [10,:,drop = F]。numpy中是否有类似的东西。我在文档中找不到它,也没有看到类似的问题。

谢谢!

Answers:


59

这可能最容易做到x[None, 10, :]或等效(但更具可读性)x[np.newaxis, 10, :]

就为什么不是默认值而言,我个人发现,不断拥有单例维度的数组会非常烦人。我猜想那些麻木的开发者也有同样的感觉。

另外,numpy可以很好地处理广播数组,因此通常没有理由保留切片所来自的数组的尺寸。如果您这样做了,那么类似:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b

要么行不通,要么实施起来更加困难。

(或者至少这是我对切片时删除维度信息背后的numpy开发人员的猜测)


6
@Lisa:x[None, 10]会做你想做的。
naught101 '16

对。将您的Nones 放在要切碎的暗处旁边。
疯狂物理学家,2016年

1
该示例在分配给b;时缺少元组的多余括号。应该是b = np.zeros((100,10))
Jerzy

为什么总共使用3个索引而不是仅使用2个索引的原因是什么?我的意思是X[10,None](以您的代码为例)。
greenoldman'9

8
通常没有什么理由保留数组的维数 ”……嗯,这肯定会完全搞定矩阵乘法(np.matmul()@)。只是被这个烧死了。
让·弗朗索瓦·科贝特

89

另一个解决方案是

X[[10],:]

要么

I = array([10])
X[I,:]

当通过索引列表(或数组)执行索引时,将保留数组的维数。这很好,因为它使您可以选择保持尺寸和压缩尺寸。


2
这将复制阵列数据
2014年

这并非总是如此。请参阅: x = np.array([[1,2,3,4]]) 如果你然后用切它 x[[0],[1,2]] 你会得到一维 array([2, 3]) 我的意见是选择行或列向量时,最好使片简单,然后使用 np.reshape,所以在我的例子这将是np.reshape(x[0,[1,2]],[1,2])
亚历山大

1
其他的,最后要注意分号-这很重要,X[[10]]将被解释为X[10]并且形状会更小;同样,X[[10, 20]] == X[10, 20]形状甚至更小
Ben Usman

1
警告:请勿将这种索引方式与整数索引混合使用!如果您具有ashape (10, 20, 30)a[0, :, [0]]则将具有shape (1, 20),而不是shape ,(20, 1)因为在后者中,广播的索引a[[0], :, [0]]通常不符合您的期望!而正如a[0, :, :1](20, 1)所料。此外,请参阅上面的注释,以了解具有单个索引的奇怪边缘情况。总的来说,这种方法似乎有太多的情况。
Ben Usman '18

30

我找到了一些合理的解决方案。

1)使用 numpy.take(X,[10],0)

2)使用这个奇怪的索引 X[10:11:, :]

理想情况下,这应该是默认设置。我从未理解过为什么尺寸会下降。但这是关于numpy的讨论...


1
在为Python列表建立索引时会删除“维度”,alist[0]而在对它们进行切片时会保留。
hpaulj

4
选项2(可以写成slice(n, n+1)提取索引n)应该是公认的答案,因为它是唯一自然地扩展到n维情况的答案。
norok2

选项2似乎可以用X[10:11, :]Python 3.7.5 编写(即11之后没有多余的冒号)
Joe

6

这是我更喜欢的替代方法。而不是使用单个数字编制索引,而是使用范围进行索引。即使用X[10:11,:]。(请注意,其中10:11不包括11)。

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10:11,:]
xslice.shape   # >> (1,10)

这也使得使用更多尺寸也很容易理解,而无需None费力地弄清楚要使用哪个索引的轴。同样,无需为数组大小做额外的记账工作,只需i:i+1i您将在常规索引中使用的任何记账工作做好。

b = np.ones((2, 3, 4))
b.shape # >> (2, 3, 4)
b[1:2,:,:].shape  # >> (1, 3, 4)
b[:, 2:3, :].shape .  # >> (2, 1, 4)


0

如果您在运行时按长度可能为1的数组建立索引,这将特别令人讨厌。对于这种情况,有np.ix_

some_array[np.ix_(row_index,column_index)]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.