【问题标题】:Conditional indexing with Numpy ndarray使用 Numpy ndarray 进行条件索引
【发布时间】:2016-01-15 02:32:40
【问题描述】:

我有一个浮点值的 Numpy ndarray 矩阵,我需要选择特定行,其中某些列的值满足某些条件。例如,假设我有以下 numpy 矩阵:

matrix = np.ndarray([4, 5])
matrix[0,:] = range(1,6)
matrix[1,:] = range(6,11)
matrix[2,:] = range(11,16)
matrix[3,:] = range(16,21)

假设我想从矩阵中选择第一列的值在 1 到 6 之间并且第二列的值在 2-7 之间的行。

如何获得满足这些条件的矩阵的行索引?如果我想删除满足条件条件的行怎么办?

【问题讨论】:

    标签: python numpy matrix indexing


    【解决方案1】:

    对于基于 numpy 的解决方案,您可以使用numpy.where,然后从中获取行索引,然后使用它来索引您的矩阵。示例 -

    matrix[np.where((1 <= matrix[:,0]) & (matrix[:,0] <= 6)
           & (2 <= matrix[:,1]) & (matrix[:,1] <= 7))]
    

    演示 -

    In [169]: matrix
    Out[169]:
    array([[  1.,   2.,   3.,   4.,   5.],
           [  6.,   7.,   8.,   9.,  10.],
           [ 11.,  12.,  13.,  14.,  15.],
           [ 16.,  17.,  18.,  19.,  20.]])
    
    In [170]: matrix[np.where((1 <= matrix[:,0]) & (matrix[:,0] <= 6)
       .....:        & (2 <= matrix[:,1]) & (matrix[:,1] <= 7))]
    Out[170]:
    array([[  1.,   2.,   3.,   4.,   5.],
           [  6.,   7.,   8.,   9.,  10.]])
    

    如 cmets 所示,另一种方法是使用布尔掩码,示例 -

    mask = ((1 <= matrix[:,0]) & (matrix[:,0] <= 6)
               & (2 <= matrix[:,1]) & (matrix[:,1] <= 7))
    
    matrix[mask,:]
    

    演示 -

    In [41]: matrix
    Out[41]:
    array([[  1.,   2.,   3.,   4.,   5.],
           [  6.,   7.,   8.,   9.,  10.],
           [ 11.,  12.,  13.,  14.,  15.],
           [ 16.,  17.,  18.,  19.,  20.]])
    
    In [42]: mask = ((1 <= matrix[:,0]) & (matrix[:,0] <= 6)
       ....:            & (2 <= matrix[:,1]) & (matrix[:,1] <= 7))
    
    In [43]:
    
    In [43]: matrix[mask,:]
    Out[43]:
    array([[  1.,   2.,   3.,   4.,   5.],
           [  6.,   7.,   8.,   9.,  10.]])
    

    【讨论】:

    • 非常感谢!我习惯于更多地使用 Matlab 的索引,所以 Python 的索引有时会让我感到困惑;D
    • 很高兴能为您提供帮助! :-) 。如果您认为这些答案有帮助,我想请您通过单击答案左侧的勾号来接受一个答案(以您认为最好的为准),这将对社区有所帮助。
    • 您可以省略 where 并仅使用布尔掩码来选择行。 mask=(1&lt;=matrix...); matrix[mask,:].
    • @hpaulj 好建议,谢谢。我已将其包含在答案中。
    【解决方案2】:

    您可以通过以下方式获取索引:

    rows = np.logical_and(0 < matrix[:, 0], < matrix[:, 0] < 6 ) *  np.logical_and(1 < matrix[:, 1], matrix[:, 1] < 7)
    

    然后newMatrix = np.delete(matrix, rows, axis = 0)

    【讨论】:

    • 谢谢,太好了!附言您是否忘记将“行”添加到第二行?
    【解决方案3】:

    您提到了 MATLAB。这是使用 Octave 接受的答案的等价物

    octave:17> ma=reshape(1:20,5,4)
    ma =
        1    6   11   16
        2    7   12   17
        3    8   13   18
        4    9   14   19
        5   10   15   20
    
    octave:18> mask=(1<=ma(1,:))&(ma(1,:)<=6)&(2<=ma(2,:))&(ma(2,:)<=7)
    mask =
       1   1   0   0
    
    octave:19> ma(:,mask)
    ans =
        1    6
        2    7
        3    8
        4    9
        5   10
    

    没有where 的公认答案是:

    In [592]: mask=(1 <= matrix[:,0]) & (matrix[:,0] <= 6) &(2 <= matrix[:,1]) & (matrix[:,1] <= 7)
    
    In [593]: matrix[mask,:]
    Out[593]: 
    array([[  1.,   2.,   3.,   4.,   5.],
           [  6.,   7.,   8.,   9.,  10.]])
    

    我在 Octave 版本中切换了行和列,因为这是生成相同数字的自然方式(MATLAB/Octave 使用相当于 numpys 'F' 顺序 - 见下文)。

    其他变化是 0 v 1 开始索引,和 () v []。否则这两个符号是相似的。

    在 numpy 中生成matrix 的更简单方法:

    In [594]: np.arange(1,21).reshape(4,5)
    Out[594]: 
    array([[ 1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10],
           [11, 12, 13, 14, 15],
           [16, 17, 18, 19, 20]])
    

    或者使用 MATLAB 布局:

    In [595]: np.arange(1,21).reshape(5,4,order='F')
    Out[595]: 
    array([[ 1,  6, 11, 16],
           [ 2,  7, 12, 17],
           [ 3,  8, 13, 18],
           [ 4,  9, 14, 19],
           [ 5, 10, 15, 20]])
    

    【讨论】:

    • 非常感谢! =) 太棒了!
    【解决方案4】:

    获取行索引:

    row_indices = [x for x in range(4) if matrix[x][0] in range(1,7) and matrix[x][1] in range(2,8)]
    

    删除行:

    indices = [x for x in range(4) if not( matrix[x][0] in range(1,7) and matrix[x][1] in range(2,8))]
    
    new_matrix = matrix[indices]
    

    【讨论】:

    • 非常感谢! =) 欣赏它
    • “in range(1, 7)”部分看起来效率极低
    • 可能还有更优雅的方法使用 numpy.where() ...仍在考虑中。
    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 2017-07-27
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多