【问题标题】:Searching 2D array with numpy.where with multiple conditions使用具有多个条件的 numpy.where 搜索二维数组
【发布时间】:2023-04-07 17:07:02
【问题描述】:

我有一个二维数组,定义如下:

traces = [['x1',11026,0,0,0,0],
          ['x0',11087,0,0,0,1],
          ['x0',11088,0,0,1,3],
          ['x0',11088,0,0,0,3],
          ['x0',11088,0,1,0,1]]

我想找到与所选列的多个条件匹配的行的索引。例如我想在这个数组中找到

row[0]=='x0' & row[1]==11088 & row[3]==1 & row[5]=1

按此条件搜索应返回 4。

我尝试使用 numpy.where 但似乎无法使其适用于多种条件

print np.where((traces[:,0] == 'x0') & (traces[:,1] == 11088) & (traces[:,3] == 1) & (traces[:,5] == 1))

以上创建警告

FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison   print np.where((traces[:,0] == 'x0') & (traces[:,1] == 11088) & (traces[:,3]
== 1) & (traces[:,5] == 1)) (array([], dtype=int32),)

我也尝试使用numpy.logical_and,但这似乎也不起作用,产生了类似的警告。

我有什么方法可以使用numpy.where 做到这一点,而无需遍历整个二维数组?

谢谢

【问题讨论】:

    标签: python python-2.7 numpy


    【解决方案1】:

    我强烈认为你做了这样的事情(转换为np.array):

    traces = [['x1',11026,0,0,0,0],
              ['x0',11087,0,0,0,1],
              ['x0',11088,0,0,1,3],
              ['x0',11088,0,0,0,3],
              ['x0',11088,0,1,0,1]]
              
    traces = np.array(traces)
    

    这表现出所描述的错误。打印结果数组可以看出原因:

    print(traces)
    # array([['x1', '11026', '0', '0', '0', '0'],
    #        ['x0', '11087', '0', '0', '0', '1'],
    #        ['x0', '11088', '0', '0', '1', '3'],
    #        ['x0', '11088', '0', '0', '0', '3'],
    #        ['x0', '11088', '0', '1', '0', '1']],
    #       dtype='<U5')
    

    数字已转换为字符串!

    在构造一个包含不同类型值的数组时,numpy 通常会创建一个dtype=object 的数组。这在大多数情况下都有效,但性能很差。

    但是,在这种情况下,numpy 显然试图变得聪明,并将数据转换为字符串类型,该类型比 object 更具体,但足够通用,可以将数字作为字符串。

    作为一种解决方案,将数组显式构造为“对象数组”:

    traces = np.array(traces, dtype='object')
    
    print(np.where((traces[:,0] == 'x0') & (traces[:,1] == 11088) & (traces[:,3] == 1) & (traces[:,5] == 1)))
    # (array([4], dtype=int32),)
    

    请注意,尽管这可行,但对象数组通常不是一个好主意。请考虑将第一列中的字符串替换为数值。

    【讨论】:

    • 你是对的,它被转换成一个 numpy 数组,我没有意识到这会将数字更改为字符串。
    • @ozal 我也对此感到惊讶;)
    【解决方案2】:

    考虑这个比较:

    >>> traces[:,[0,1,3,5]] == ['x0', 11088, 1, 1]
    array([[False, False, False, False],
           [ True, False, False,  True],
           [ True,  True, False, False],
           [ True,  True, False, False],
           [ True,  True,  True,  True]])
    

    我们正在寻找所有值都等于 True 的一行(或多行):

    >>> np.where(np.all(traces[:,[0,1,3,5]] == ['x0', 11088, 1, 1], axis=1))
    (array([4]),)
    

    【讨论】:

    • 谢谢,这是一个非常优雅的解决方案。这里axis=1的目的是什么?
    • 沿指定轴求和,在这种情况下按行求和。
    • 更好地使用np.all insteaf of np.sum,它更优雅(如果重要的话应该表现更好)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多