【问题标题】:How do I select elements of an array given condition?如何在给定条件下选择数组的元素?
【发布时间】:2011-03-03 02:37:36
【问题描述】:

假设我有一个 numpy 数组 x = [5, 2, 3, 1, 4, 5]y = ['f', 'o', 'o', 'b', 'a', 'r']。我想选择y中大于1小于5的元素对应x中的元素。

我试过了

x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']

但这不起作用。我该怎么做?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    如果您添加括号,您的表达式有效:

    >>> y[(1 < x) & (x < 5)]
    array(['o', 'o', 'a'], 
          dtype='|S1')
    

    【讨论】:

    • 很好.. vecMask=1
    • @JennyYueJin:这是因为优先级。 (按位)&amp; 的优先级高于 &lt;&gt;,而后者又高于(逻辑)andx &gt; 1 and x &lt; 5 先评估不等式,然后评估逻辑合取; x &gt; 1 &amp; x &lt; 5 计算 1 和(中的值)x 的按位连接,然后计算不等式。 (x &gt; 1) &amp; (x &lt; 5) 强制首先评估不等式,因此所有操作都按预期顺序进行,并且结果都是明确定义的。 See docs here.
    • @ru111 它也适用于 Python 3.6(没有理由停止工作)。
    • 我得到“ValueError:包含多个元素的数组的真值不明确。使用 a.any() 或 a.all()”
    • @ru111 你应该写(0 &lt; x) &amp; (x &lt; 10)(如答案所示)而不是0 &lt; x &lt; 10,这不适用于任何Python版本上的numpy数组。
    【解决方案2】:

    IMO OP 实际上并不想要 np.bitwise_and() (aka &amp;),但实际上想要 np.logical_and(),因为他们正在比较诸如 TrueFalse 之类的逻辑值 - 请参阅 logical vs. bitwise 上的此 SO 帖子以查看差异。

    >>> x = array([5, 2, 3, 1, 4, 5])
    >>> y = array(['f','o','o','b','a','r'])
    >>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
    >>> output
    array(['o', 'o', 'a'],
          dtype='|S1')
    

    等效的方法是使用np.all(),通过适当地设置axis 参数。

    >>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
    >>> output
    array(['o', 'o', 'a'],
          dtype='|S1')
    

    按数字:

    >>> %timeit (a < b) & (b < c)
    The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
    100000 loops, best of 3: 1.15 µs per loop
    
    >>> %timeit np.logical_and(a < b, b < c)
    The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
    1000000 loops, best of 3: 1.17 µs per loop
    
    >>> %timeit np.all([a < b, b < c], 0)
    The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
    100000 loops, best of 3: 5.06 µs per loop
    

    所以使用np.all() 比较慢,但&amp;logical_and 差不多。

    【讨论】:

    • 您在谈论评估内容时需要小心谨慎。例如,在output = y[np.logical_and(x &gt; 1, x &lt; 5)] 中,x &lt; 5 求值(可能创建一个巨大的数组),即使它是第二个参数,因为该求值发生在函数之外。 IOW,logical_and 被传递了两个已经评估过的参数。这与a and b 的通常情况不同,在这种情况下,如果a 为真,则不会评估b
    • 布尔数组的bitwise_and()和logical_and()没有区别
    • 我一直在寻找“或”替代方案,这个回复给了我一些急需的解脱!太感谢了。 (np.logical_or),显然...
    • @J.Massey a pipe | (aka np.bitwise_or) 也可能有效,例如(a &lt; b) | (a &gt; c)
    【解决方案3】:

    向@J.F. 添加一个细节。 Sebastian 和@Mark Mikofski 的回答:
    如果想得到对应的索引(而不是数组的实际值),下面的代码就可以了:

    为了满足多个(所有)条件:

    select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] #   1 < x <5
    

    满足多个(或)条件:

    select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5
    

    【讨论】:

    • 请注意,numpy.where 不仅会返回一个索引数组,而是会返回一个包含数组的元组(condition.nonzero() 的输出)——在这种情况下,(the array of indices you want,),所以你需要select_indices = np.where(...)[0] 来获得你想要和期望的结果。
    【解决方案4】:

    我喜欢将np.vectorize 用于此类任务。考虑以下几点:

    >>> # Arrays
    >>> x = np.array([5, 2, 3, 1, 4, 5])
    >>> y = np.array(['f','o','o','b','a','r'])
    
    >>> # Function containing the constraints
    >>> func = np.vectorize(lambda t: t>1 and t<5)
    
    >>> # Call function on x
    >>> y[func(x)]
    >>> array(['o', 'o', 'a'], dtype='<U1')
    

    优点是您可以在矢量化函数中添加更多类型的约束。

    希望对你有帮助。

    【讨论】:

    • 这不是在 NumPy 中进行索引的好方法(它会很慢)。
    【解决方案5】:

    其实我会这样做:

    L1是满足条件1的元素的索引列表;(或许你可以使用somelist.index(condition1)或者np.where(condition1)来获取L1。)

    同样,你得到 L2,一个满足条件 2 的元素列表;

    然后你使用intersect(L1,L2)找到交集。

    如果满足多个条件,还可以找到多个列表的交集。

    然后您可以在任何其他数组中应用索引,例如 x。

    【讨论】:

      【解决方案6】:

      对于二维数组,您可以这样做。使用条件创建 2D 蒙版。将条件掩码类型转换为 int 或 float,具体取决于数组,并将其与原始数组相乘。

      In [8]: arr
      Out[8]: 
      array([[ 1.,  2.,  3.,  4.,  5.],
             [ 6.,  7.,  8.,  9., 10.]])
      
      In [9]: arr*(arr % 2 == 0).astype(np.int) 
      Out[9]: 
      array([[ 0.,  2.,  0.,  4.,  0.],
             [ 6.,  0.,  8.,  0., 10.]])
      

      【讨论】:

        猜你喜欢
        • 2017-03-01
        • 2016-10-12
        • 1970-01-01
        • 2021-09-04
        • 1970-01-01
        • 2011-04-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-01
        相关资源
        最近更新 更多