Python Numpy索引切片而不丢失维度信息

Python Numpy索引切片而不丢失维度信息,python,numpy,Python,Numpy,我正在使用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中有类似的东西吗。我在文档中找不到,也没有看到类似的问题

我正在使用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中有类似的东西吗。我在文档中找不到,也没有看到类似的问题


谢谢

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

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

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


理想情况下,这应该是默认值。我一直不明白为什么维度会下降。但这是对numpy的讨论…

这可能是最容易做到的
x[None,10,:]
或同等方式(但可读性更高)
x[np.newaxis,10,:]

至于为什么它不是默认值,我个人发现,不断使用具有单例维度的数组很快就会让人恼火。我猜numpy开发者也有同样的感觉

另外,numpy可以很好地处理广播阵列,因此通常没有什么理由保留切片所来自的阵列的尺寸。如果你做了,那么像这样的事情:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b
要么不起作用,要么更难实施


(或者至少我猜测numpy开发人员在切片时删除维度信息的原因是这样的)

另一个解决方案是这样做

X[[10],:]


当索引由索引列表(或数组)执行时,数组的维数将保持不变。这很好,因为它让你在保持维度和压缩之间做出选择。

这里有一个我更喜欢的选择。使用范围索引,而不是使用单个数字索引。也就是说,使用
X[10:11,:]
。(请注意,
10:11
不包括11)

这使得更多维度也更容易理解,无需调整和计算使用哪个索引的轴。也不需要对数组大小做额外的簿记,只需对常规索引中使用的任何
i
进行
i:i+1

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)
要通过gnebehay添加到,还可以使用元组:

X[(10,),:]

如果您使用的数组在运行时的长度可能为1,那么这尤其令人恼火。在这种情况下,有
np.ix

some_array[np.ix_(row_index,column_index)]

这会复制阵列数据,但情况并非总是如此。请参阅:
x=np.array([[1,2,3,4]])
如果然后使用
x[[0],[1,2]]对其进行切片
您将得到一维
数组([2,3])
我的意见是,在选择列向量或行向量时,最好简化切片,然后使用
np.reformate
,因此在我的示例中是
np.reformate(x[0,1,2],[1,2])
其他人,最后要注意分号-这很重要,
X[[10]]
将被解释为
X[10]
并且形状会更小;类似地,
X[[10,20]==X[10,20]
和shape甚至更小警告:不要将这种索引方式与整数索引混合使用!如果你有
a
的形状
(10,20,30)
,那么
a[0,:,[0]
将有
(1,20)
,而不是
(20,1)
,因为在后一种情况下,索引被广播到
a[[0],:,[0]
,这通常不是你所期望的!而
a[0,:,:1]
将按预期为您提供
(20,1)
。此外,关于单索引的奇怪边缘情况,请参见上面的注释。总的来说,这个方法似乎有太多的边缘案例。@Lisa:
x[None,10]
可以满足您的需要。是的。将你的
None
s放在你正在切割的DIM旁边。示例是
b
赋值中元组缺少额外的括号;它应该是
b=np.zero((100,10))
。为什么总共使用3个索引而不是仅使用两个?我的意思是
X[10,None]
(以您的代码为例)。“通常没有什么理由保留数组的维度”。。。当然,它会彻底地搞砸矩阵乘法()。刚刚被这个问题烧坏了。在为Python列表编制索引时,“维度”会被删除,
alist[0]
并在对它们进行切片时保留。选项2(可以写成
slice(n,n+1)
用于提取索引
n
)应该是可接受的答案,因为它是唯一一个自然扩展到n维情况的选项。选项2似乎能够在Python 3.7.5中写成
X[10:11,:]
(即在11后面没有额外的冒号)
X[(10,),:]
some_array[np.ix_(row_index,column_index)]