使用Numpy进行类似MATLAB的数组索引

cls*_*udt 10 matlab numpy python-3.x

在MATLAB和Numpy中,数组都可以通过数组索引.但是,行为是不同的.让我通过一个例子解释一下.

MATLAB:

>> A = rand(5,5)

A =

    0.1622    0.6020    0.4505    0.8258    0.1067
    0.7943    0.2630    0.0838    0.5383    0.9619
    0.3112    0.6541    0.2290    0.9961    0.0046
    0.5285    0.6892    0.9133    0.0782    0.7749
    0.1656    0.7482    0.1524    0.4427    0.8173

>> A([1,3,5],[1,3,5])

ans =

    0.1622    0.4505    0.1067
    0.3112    0.2290    0.0046
    0.1656    0.1524    0.8173
Run Code Online (Sandbox Code Playgroud)

NumPy的:

In [2]: A = arange(25).reshape((5,5))

In [3]: A
Out[3]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

In [6]: A[[0,2,4], [0,2,4]]
Out[6]: array([ 0, 12, 24])
Run Code Online (Sandbox Code Playgroud)

用语言:MATLAB选择行和列,Numpy"拉链"两个索引数组并使用元组指向条目.

如何通过Numpy获得MATLAB行为?

rob*_*nce 16

您可以使用辅助函数numpy.ix_来获取Matlab行为:

from numpy import ix_
A[ ix_( [0,2,4], [0,2,4] ) ]
Run Code Online (Sandbox Code Playgroud)


Gar*_*han 10

你可以这样做:

A[[0,2,4],:][:,[0,2,4]]
Run Code Online (Sandbox Code Playgroud)

这将给出你想要的类似MATLAB的结果.

值得注意的是,相当不一致,如果你使用切片进行索引,那么你就可以获得类似MATLAB的结果,而不需要任何这样的hackery:

>>> A[1:3,1:3]
array([[ 6, 7],
       [11,12]])
Run Code Online (Sandbox Code Playgroud)

与MATLAB不同,1:3它不仅仅是一种缩写,[1,2]也不是任何类型的缩写.(此时我觉得有必要提一下你肯定已经知道的东西,即Python 1:3有点像,[1,2]而MATLAB有点像[1,2,3]:右手端点包含在MATLAB中并在Python中排除.)

  • 这实际上是非常低效的.它需要在内存中创建一个可能非常大的临时数组,具体取决于您正在使用的数组的大小.有几种更有效的方法可以做到这一点,包括使用ix_ helper函数. (3认同)
  • 是的,一切都正确.另一方面,由`ix_`构造的东西也很大,虽然是暂时的.我在原始问题中为5x5阵列做了一些计时实验,结果如下.`[,:] [:,]`比`[ix _()]`快约25%,但是如果你每次使用相同的索引然后用`ix_`构造一个索引数组**并重复使用它大约快10倍 - 当然,然后你需要花费内存使用成本. (2认同)
  • 在大多数情况下,np.ix_只使用了大量的内存,因为它返回了它的参数的视图.此外,np.ix_是一个恒定时间操作,而A [I1,:] [:,I2]在时间和内存使用方面都是~n ^ 2.但是如果你真的需要在你的5x5阵列上提高25%的性能,你必须做你应该做的事情. (2认同)