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

min*_*ers 80 python numpy

我正在使用numpy并希望索引一行而不会丢失维度信息.

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

在这个例子中,xslice现在是1维,但我希望它是(1,10).在R中,我会使用X [10,:,drop = F].numpy中有类似的东西吗?我在文档中找不到它,也没有看到类似的问题.

谢谢!

gne*_*hay 81

另一种解决方案是做

X[[10],:]
Run Code Online (Sandbox Code Playgroud)

要么

I = array([10])
X[I,:]
Run Code Online (Sandbox Code Playgroud)

当索引的列表(或数组)执行索引时,将保留数组的维度.这很好,因为它让您可以选择保持尺寸和挤压.

  • 这会复制数组数据 (2认同)
  • **警告**:不要将这种索引方式与整数索引混合使用!如果你有一个形状为 (10, 20, 30) 的 `a`,那么 `a[0, :, [0]]` 的形状将是 `(1, 20)`,而不是 `(20, 1)` ,因为在后者中索引被广播到 `a[[0], :, [0]]` 这通常不是你所期望的!而 `a[0, :, :1]` 会如预期的那样给你 `(20, 1)`。此外,请参阅上面关于单个索引的奇怪边缘情况的评论。总的来说,这种方法似乎有太多的边缘情况。 (2认同)

Joe*_*ton 47

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

至于为什么它不是默认值,就个人而言,我发现不断地使用具有单一尺寸的阵列会很快变得烦人.我猜这些笨拙的开发者也有同感.

而且,numpy处理广播阵列非常好,所以通常没有理由保留切片来自的数组的维度.如果你这样做,那么事情如下:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b
Run Code Online (Sandbox Code Playgroud)

要么不起作用,要么实施起来要困难得多.

(或者至少那是我猜测numpy dev在切片时丢弃尺寸信息背后的推理)

  • “ *通常没有什么理由保留数组的维数*” ...嗯,肯定会完全搞定矩阵乘法([`np.matmul()`或`@`](https:/ /docs.scipy.org/doc/numpy/reference/generation/numpy.dot.html))。只是被这个烧死了。 (6认同)
  • @Lisa:`x [无,10]`会做你想要的. (5认同)
  • 实际上,`x [10,:,None]`返回形状为(10,1)而不是(1,10)的数组。 (2认同)

min*_*ers 26

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

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

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

理想情况下,这应该是默认值.我永远不明白为什么尺寸会掉落.但这是对numpy的讨论......

  • 选项2(可以写成`slice(n,n + 1)`用于提取索引`n`)应该是接受的答案,因为它是唯一一个自然延伸到n维情况的答案. (3认同)
  • 'dimensions' 在索引 Python 列表时被删除,`alist[0]` 并在切片时保留。 (2认同)

And*_*rtz 11

这是我更喜欢的替代方案。不是用单个数字索引,而是用一个范围索引。也就是说,使用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)
Run Code Online (Sandbox Code Playgroud)

这也使得使用更多维度更容易理解,无需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)
Run Code Online (Sandbox Code Playgroud)