即使是MATLAB/Octave也会挤出多余的维度:
>> ones(2,3,4)(:,:,1)
ans =
1 1 1
1 1 1
>> size(ones(2,3,4)(1,:)) # some indexing "flattens" outer dims
ans =
1 12
当我开始使用MATLAB v3.5时,它只有2D矩阵;单元格、结构和更高维度的内容是后来添加的(如上例所示)。
In [760]: A=np.arange(6).reshape(2,3)
In [762]: np.array([A[:,0]]).T
Out[762]:
array([[0],
[3]])
这段代码比必要的复杂。它首先创建一个列表,然后从中创建一个 (1,N) 的数组,最后是一个 (N,1) 的数组。
A[:,[0]]
, A[:,:,None]
, A[:,0:1]
更直接。甚至可以使用 A[:,0].reshape(-1,1)
我无法想到一些简单的方法来同时处理标量和列表索引。
像 np.atleast_2d
这样的函数可以有条件地添加新维度,但它将成为一个前导(外部)维度。但根据广播的规则,前导维度通常是“自动”的。
基本索引与高级索引
在底层 Python 中,标量不能被索引,而列表只能用标量和切片进行索引。底层语法允许使用元组进行索引,但列表会拒绝这些元组。扩展了索引功能的不是语法,而是 numpy
如何处理这些元组。
numpy
使用切片和标量进行索引是 basic
索引。这是可能丢失维度的地方。这与列表索引一致。
In [768]: [[1,2,3],[4,5,6]][1]
Out[768]: [4, 5, 6]
In [769]: np.array([[1,2,3],[4,5,6]])[1]
Out[769]: array([4, 5, 6])
使用列表和数组进行索引是高级索引,没有任何列表对应项。这可能是MATLAB和numpy
之间差异最丑陋的地方 :)
>> A([1,2],[1,2])
生成一个 (2,2) 的块。在 numpy 中,这会产生一个 "对角线"。
In [781]: A[[0,1],[0,1]]
Out[781]: array([0, 4])
要获取块,我们必须使用列表(或数组),它们会相互“广播”:
In [782]: A[[[0],[1]],[0,1]]
Out[782]:
array([[0, 1],
[3, 4]])
要在MATLAB中获得“对角线”,我们需要使用
sub2ind([2,2],[1,2],[1,2])
来获取[1,4]平面索引。
是什么类型的乘法?
在
np.array([A[:,i]]).T * np.array([B[j,:]])
这个元素级别的 (.*
) 还是矩阵级别的?
对于 (N,1) 和 (1,M) 的组合,A*B
和 A@B
产生相同的 (N,M) 结果,但一个使用了广播来推广外积,另一个是内部/矩阵乘积(带有乘积总和)。
numpy
中,一个二维的“数组”不是“矩阵”。当选择切片时,它仍然是一个“数组”。你的问题似乎是:“我能在numpy
中使用MATLAB语法吗?”答案是:不行,你必须学习“numpy”才能使用它。 - Michael Szczesny