【问题标题】:First occurrence in numpy logicsnumpy 逻辑中的第一次出现
【发布时间】:2017-08-23 20:23:38
【问题描述】:

假设我有一个numpy.ndarray

a = np.array([0,4,10,0,11,10])

我将此与 10 进行了比较。

a >= 10
# array([False, False,  True, False,  True,  True], dtype=bool)

我想要单个 True,即仅在 第一次出现时为 True。

我想将此应用于 n-D numpy.ndarray 中的给定轴。(例如,1000*1000*10)

a_2d = np.array([[0,4,10],[0,11,10]])
#if axis == 1: array([[False, False, True], [False, True, False]])

我做了什么:

对于一维数组,我使用this 设法做到了。

b=np.zeros(a.size)
b[np.argmax(a>=10)]=True
#b=array([ 0.,  0.,  1.,  0.,  0.,  0.])

但是,我不知道如何将其应用于大型 n-D 数组

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    对于 1D 或 2D,这个应该不使用 for 循环:

    def firstByRow(a, f = lambda x: x >= 10):
        b = (np.cumsum(f(a), axis = -1) == 1).T
        b[1:] = b[1:] * np.equal(b[1:], np.diff((f(a)).astype(int), axis = -1).T)
        return b.T
    

    不确定它是否会比稍微循环一些的代码更快,因为 cumsumdiff 都这样做

    编辑:

    您也可以这样做,这可能会更快(利用np.unique(return_index = True) 选择第一次出现):

    def firstByAxis(a, f = lambda x: x >= 10, axis = 0):
        c = np.where(f(a))
        i = np.unique(c[axis], return_index = True)[1]
        b = np.zeros_like(a)
        b[tuple(np.take(c, i, axis = -1))] = 1
        return b
    

    【讨论】:

    • 第二个看起来很棒。只是我想你忘了定义b = np.zeros(a.shape) 有没有办法在这个方法中添加轴?我相信它与 np.unique 有关,但我无法管理它。
    • 我确实忘记了零,抱歉。您可以将r 更改为c 作为np.unique 的参数,以按列执行相同的操作
    • 在函数中添加了一个轴
    【解决方案2】:

    您可以尝试以下方法:

    >>> import numpy as np
    >>> a_2d = np.array([[0,4,10],[0,11,10]])
    >>> r, c = np.where( a_2d >= 10 )
    >>> mask = r+c == (r+c).min()
    >>> highMask = np.zeros(np.shape(a_2d))
    >>> highMask[r[mask], c[mask]] = 1
    >>> highMask
        array([[ 0.,  0.,  1.],
               [ 0.,  1.,  0.]])
    

    在二维数组中没有“第一个”这样的东西。在 2D 数组中,最小索引将在 2D 轴上形成一条线,两者都将具有最小索引值。对于 3D 矩阵,这将是一个表面等..

    这样一行的例子是:

     0 0 0 0 0 1
     0 0 0 0 1 0
     0 0 0 1 0 0
     0 0 1 0 0 0
     0 1 0 0 0 0
     1 0 0 0 0 0
    

    所有这些都与 [0,0] 位置等距...

    【讨论】:

      【解决方案3】:

      如果您 enumerate 超过 argmax,则可以更新您的 zeros 数组。

      代码:

      a = np.array([[0, 4, 10], [0, 11, 10]])
      print(a)
      
      b = np.zeros(a.shape)
      for i, j in enumerate(np.argmax(a >= 10, axis=1)):
          b[i, j] = 1
      print(b)
      

      结果:

      [[ 0  4 10]
       [ 0 11 10]]
      
      [[ 0.  0.  1.]
       [ 0.  1.  0.]]
      

      使用高级索引:

      c = np.zeros(a.shape)
      c[list(range(a.shape[0])), np.argmax(a >= 10, axis=1)] = 1
      

      【讨论】:

      • 感谢您的回答。但是,我想避免使用“for 循环”(因为这是我使用 Numpy 的主要原因)
      • 这只是每列一个循环。加速在 argmax 中。
      • 我应该补充一下,列数也相当大。
      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 2013-04-21
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 2017-09-14
      • 1970-01-01
      相关资源
      最近更新 更多