Numpy中的矩阵索引

9

在开发一个涉及矩阵操作的小Python脚本时,我感到有些困惑,因此我启动了一个shell来使用一个玩具示例并更好地了解Numpy中的矩阵索引。

我所做的是这样的:

>>> import numpy as np
>>> A = np.matrix([1,2,3])
>>> A
matrix([[1, 2, 3]])
>>> A[0]
matrix([[1, 2, 3]])
>>> A[0][0]
matrix([[1, 2, 3]])
>>> A[0][0][0]
matrix([[1, 2, 3]])
>>> A[0][0][0][0]
matrix([[1, 2, 3]])

正如您所想象的那样,这并没有帮助我更好地理解Numpy中的矩阵索引。对于我描述为“一个由自身组成的数组”的东西,这种行为是有意义的,但我怀疑任何正常的人都不会选择它作为科学库中矩阵的模型。
那么,我得到的输出逻辑是什么?为什么矩阵对象的第一个元素是它本身?
注:我知道如何获取矩阵的第一个条目。我感兴趣的是这个设计决策背后的逻辑。
编辑:我不是在问如何访问矩阵元素,也不是在问为什么矩阵行的行为像矩阵一样。我正在询问单个数字索引矩阵时矩阵的行为定义。这是数组的典型操作,但结果行为与您从数组中期望的行为完全不同。我想知道这是如何实现的,这个设计决策背后的逻辑是什么。

2
语法为 A[dim1, dim2, ...]。对于这种情况,要获取第一个元素,应使用 A[0,0],第二个元素为 A[0,1],第三个元素为 A[0,2]。这是一个 1 x 3 矩阵。 - Gopala
有人真的读了 PS 吗? - cangrejo
2
matrix 类被硬编码为始终具有两个维度(即行和列)。这通过切片和索引操作进行保留(除非您访问单个元素,例如 A [0,0])。顺便说一句,对于大多数用途,首选 ndarray 类(即标准的 numpy 数组);搜索“numpy array vs matrix”以找到有关此主题的大量讨论。 - Warren Weckesser
当我第一次需要在NumPy中进行矩阵数学运算时,所有可以找到的帮助都指导我使用ndarray。它更加灵活,并且在我测试的每个事项中速度更快。 - paddyg
2个回答

8

索引后查看形状:

In [295]: A=np.matrix([1,2,3])
In [296]: A.shape
Out[296]: (1, 3)
In [297]: A[0]
Out[297]: matrix([[1, 2, 3]])
In [298]: A[0].shape
Out[298]: (1, 3)

这种行为的关键在于np.matrix始终是2D的。因此,即使您选择一行(A[0,:] ),结果仍然是2D,形状为(1,3)。因此,您可以串联任意数量的 [0] ,但不会发生任何新的变化。
您想通过A[0][0]实现什么目的?与A[0,0]相同吗? 对于基本的np.ndarray类来说,这两者是等效的。
请注意,Python解释器将索引转换为__getitem__调用。
 A.__getitem__(0).__getitem__(0)
 A.__getitem__((0,0))

[0][0] 是两次索引操作,而不是一次。因此第二个 [0] 的效果取决于第一个产生的结果。

对于一个数组,A[0,0] 等同于 A[0,:][0]。但对于矩阵,你需要这样做:

In [299]: A[0,:][:,0]
Out[299]: matrix([[1]])  # still 2d

=============================

"它本身的数组",但我怀疑任何理智的人都不会选择它作为科学库中矩阵的模型。

那么,我得到的输出逻辑是什么?为什么一个矩阵对象的第一个元素是它本身?

此外,A [0,:]与A [0]不同

鉴于这些评论,让我提出一些澄清意见。

A [0]并不意味着“返回第1个元素”。它表示沿着第1轴进行选择。对于1d数组,这意味着第1个项目。对于2d数组,它表示第1行。对于ndarray来说,这将是一个1d数组,但对于matrix来说,它是另一个matrix。因此,对于2d数组或矩阵,A [i,:] A[i]是相同的。

A [0]并不只返回它本身。它返回一个新的矩阵。不同的id:

In [303]: id(A)
Out[303]: 2994367932
In [304]: id(A[0])
Out[304]: 2994532108

它可能具有相同的数据、形状和步幅,但它是一个新对象。 它和有许多行的矩阵中的第i行一样独特。
大部分独特的“matrix”活动都在“numpy/matrixlib/defmatrix.py”中定义。我原本想建议查看“matrix.__getitem__”方法,但大部分操作是在“np.ndarray.__getitem__”中执行的。
“np.matrix”类被添加到“numpy”中,作为老派MATLAB程序员的便利。 “numpy”数组可以具有几乎任意数量的维度,0、1…… MATLAB仅允许2个,尽管在2000年左右的版本中将其推广到2个以上。

我不明白矩阵始终是二维的行为如何导致这种情况。此外,A [0,:]与A [0]不同(即使它们在这种情况下产生相同的结果),因此numpy中的矩阵行是矩阵并不能解释我发布的行为。然而,有趣的是,索引转换为__getitem__。看到实现可能会阐明这一点。我不明白的是,如果其行为不是数组的行为,为什么要在类中实现数组操作。索引数组通常返回的不是数组本身。 - cangrejo

1
想象你有以下内容:
>> A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]]) 

如果您想获取第二列的值,请使用以下代码:
>> A.T[1]
array([ 2,  6, 10])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接