【问题标题】:Python - how to correctly index numpy array with other numpy arrays, similarly to MATLABPython - 如何使用其他 numpy 数组正确索引 numpy 数组,类似于 MATLAB
【发布时间】:2017-08-15 04:35:04
【问题描述】:

在使用 MATLAB 多年后,我正在尝试学习 python,这是我真正坚持的东西。我有一个数组,比如 10 x 8。我想在第一列中找到值为 3 的行,并在该行中取列“2:”。我要做的是:

newArray = oldArray[np.asarray(np.where(oldArray[:,0] == 3)), 2:]

但这会创建一个第一维为 1 的 3 维数组,而不是 2 维数组。我正在尝试实现 MATLAB 等效的

newArray = oldArray(find(oldArray(:,1)==3),3:end);

有人对如何做到这一点有任何想法吗?谢谢!

【问题讨论】:

    标签: python arrays matlab numpy indexing


    【解决方案1】:

    Slice 第一列并与3 比较,为我们提供选择行的掩码。通过索引输入数组的2D 数组的第一个轴/行来选择行后,我们需要选择列(数组的第二个轴)。在您的 MATLAB 代码中,您有 3:end,这将在 NumPy 上转换为 2:。在 MATLAB 中,您需要指定结束索引,而在 NumPy 中则不需要。因此,与 MATLAB 上的 3:end 相比,它简化为 2:

    因此,代码将是 -

    oldArray[oldArray[:,0]==3,2:]
    

    示例运行 -

    In [352]: a
    Out[352]:    |===============>|
    array([[1, 0, 4, 2, 0, 1, 3, 2],
           [1, 0, 0, 3, 2, 3, 4, 4],
           [1, 2, 1, 4, 4, 0, 4, 2],
           [0, 2, 0, 3, 2, 2, 1, 2],
           [1, 2, 3, 3, 1, 0, 0, 1],
           [3, 4, 2, 4, 2, 0, 3, 4],  <==
           [3, 1, 1, 0, 0, 1, 2, 0],  <==
           [2, 0, 4, 3, 1, 3, 1, 1],
           [4, 3, 1, 3, 1, 3, 4, 4],
           [2, 0, 2, 0, 3, 1, 1, 1]])
    
    In [353]: a[a[:,0]==3,2:]
    Out[353]: 
    array([[2, 4, 2, 0, 3, 4],
           [1, 0, 0, 1, 2, 0]])
    

    审查您的代码 -

    你的代码是 -

    In [359]: a[np.asarray(np.where(a[:,0] == 3)), 2:]
    Out[359]: 
    array([[[2, 4, 2, 0, 3, 4],
            [1, 0, 0, 1, 2, 0]]])
    

    这也可以,但会创建问题中列出的 3D 数组。

    剖析它-

    In [361]: np.where(a[:,0] == 3)
    Out[361]: (array([5, 6]),)
    

    我们看到np.where 是一个数组元组,它们是行索引和列索引。对于1D 的一部分,您不会同时拥有行和列,但是 只有一个索引数组。

    在 MATLAB 中,find 为您提供了一个索引数组,因此减少了混淆 -

    >> a
    a =
         3     4     3     3
         2     5     5     2
         2     2     2     3
         5     3     4     4
         4     3     4     2
         3     2     4     2
    >> find(a(:,1)==3)
    ans =
         1
         6
    

    因此,要获取这些索引,请从中取出第一个数组 -

    In [362]: np.where(a[:,0] == 3)[0]
    Out[362]: array([5, 6])
    

    使用它来索引到第一个轴,然后从2 开始对列进行切片-

    In [363]: a[np.where(a[:,0] == 3)[0]]
    Out[363]: 
    array([[3, 4, 2, 4, 2, 0, 3, 4],
           [3, 1, 1, 0, 0, 1, 2, 0]])
    
    In [364]: a[np.where(a[:,0] == 3)[0],2:]
    Out[364]: 
    array([[2, 4, 2, 0, 3, 4],
           [1, 0, 0, 1, 2, 0]])
    

    这会给你预期的输出。


    注意事项

    使用掩码或整数索引轴时需要小心。

    理论上,那里的列索引应该等同于使用[2,3,4,5,6,7]a8 columns 进行索引。

    让我们试试吧-

    In [370]: a[a[:,0]==3,[2,3,4,5,6,7]]
    ....
    IndexError: shape mismatch: indexing arrays could ...
         not be broadcast together with shapes (2,) (6,) 
    

    我们正在那里触发 broadcastable 索引。用于索引到两个轴的元素长度不同,不可广播。

    让我们验证一下。用于索引到rows 的数组 -

    In [374]: a[:,0]==3
    Out[374]: array([False, False, False, False, False,  True,  True, False, False, False], dtype=bool)
    

    本质上这是一个由两个元素组成的数组,因为有两个 True elems -

    In [375]: np.where(a[:,0]==3)[0]
    Out[375]: array([5, 6])
    

    用于索引列的数组是[2,3,4,5,6,7],其长度为6,因此不能针对行索引进行广播。

    为了达到我们想要的选择行 ID 的目标:5,6 并为每一行选择列 ID 2,3,4,5,6,7,我们可以使用可广播的np._ix 创建open meshes,就像这样 -

    In [376]: np.ix_(a[:,0]==3, [2,3,4,5,6,7])
    Out[376]: 
    (array([[5],
            [6]]), array([[2, 3, 4, 5, 6, 7]]))
    

    最后,用所需的 o/p 索引输入数组 -

    In [377]: a[np.ix_(a[:,0]==3, [2,3,4,5,6,7])]
    Out[377]: 
    array([[2, 4, 2, 0, 3, 4],
           [1, 0, 0, 1, 2, 0]])
    

    【讨论】:

    • 当心 - 这是混合了基本和高级索引,可以提供weird surprises
    • @user2357112 感谢您指出!编辑了一些关于如何在此处应用的详细信息。
    • 呸,这很有道理。非常感谢您的详尽回答!
    猜你喜欢
    • 2012-07-08
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    相关资源
    最近更新 更多