代码之家  ›  专栏  ›  技术社区  ›  user121

如何将numpy数组中的所有值替换为零(除了一个特定值)?

  •  4
  • user121  · 技术社区  · 8 年前

    我有一个具有“n”唯一值的2D numpy数组。 我想生成一个二进制矩阵,其中所有值都替换为 “零”和我指定的值被指定为“一”。

    例如,我有一个数组,如下所示,我需要所有实例 共35个被分配为“一”:

    array([[12, 35, 12, 26],
           [35, 35, 12, 26]])
    

    我正在尝试获得以下输出:

    array([[0, 1, 0, 0],
           [1, 1, 0, 0]])
    

    在Python中最有效的方法是什么?

    6 回复  |  直到 8 年前
        1
  •  12
  •   yuji    8 年前
    import numpy as np
    x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
    (x == 35).astype(int)
    

    将为您提供:

    array([[0, 1, 0, 0],
           [1, 1, 0, 0]])
    

    numpy中的==运算符执行元素级比较,将布尔值转换为int时,True编码为1,False编码为0。

        2
  •  6
  •   kmario23 Mazdak    8 年前

    与所有其他解决方案相比,一种更优雅的方法是 np.isin()

    >>> arr
    array([[12, 35, 12, 26],
           [35, 35, 12, 26]])
    
    # get the result as binary matrix
    >>> np.isin(arr, 35).astype(np.uint8)
    array([[0, 1, 0, 0],
           [1, 1, 0, 0]])
    

    np。isin() 将返回 布尔掩码 具有 True 给定元素(此处 35 )存在于原始数组中,并且 False 在别处


    另一种变体是使用 np.asarray() 具有数据类型 np.uint8 为了提高速度:

    In [18]: np.asarray(np.isin(x, 35), dtype=np.uint8)
    Out[18]: 
    array([[0, 1, 0, 0],
           [1, 1, 0, 0]], dtype=uint8)
    

    标杆管理

    通过将布尔结果显式转换为 uint8 ,我们可以获得 性能提高3倍 . (感谢 @Divakar 为了指出这一点!)请参见以下计时:

    # setup (large) input array
    In [3]: x = np.arange(25000000)
    In [4]: x[0] = 35
    In [5]: x[1000000] = 35
    In [6]: x[2000000] = 35
    In [7]: x[-1] = 35
    In [8]: x = x.reshape((5000, 5000))
    
    # timings
    In [20]: %timeit np.where(x==35, 1, 0)
    427 ms ± 25.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    In [21]: %timeit (x == 35) + 0
    450 ms ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    In [22]: %timeit (x == 35).astype(np.uint8)
    126 ms ± 37.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    # the fastest choice to go for!    
    In [23]: %timeit np.isin(x, 35).astype(np.uint8)
    115 ms ± 2.21 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    In [24]: %timeit np.asarray(np.isin(x, 35), dtype=np.uint8)
    117 ms ± 2.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    如果你想要一匹真正的战马,那么使用 numexpr 如下所示:

    In [8]: import numexpr as ne
    
    In [9]: %timeit ne.evaluate("x==35").astype(np.uint8)
    23 ms ± 2.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    这是 大约快20倍 比使用基于NumPy的计算的最慢方法。


    最后,如果 意见 没关系,我们可以通过NumPy方法本身获得如此疯狂的加速。

    In [13]: %timeit (x == 35).view(np.uint8)
    20.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    In [15]: %timeit np.isin(x, 35).view(np.uint8)
    30.2 ms ± 1.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    

    (再次感谢 @迪瓦卡 用于提及 these super nice tricks !)

        3
  •  4
  •   juanpa.arrivillaga    8 年前
    import numpy as np
    x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
    (x == 35) + 0
    

    数组([[0,1,0,0], [1, 1, 0, 0]])

        4
  •  3
  •   Cleb    8 年前

    另一种选择是使用 np.where ; 此解决方案比 @yuji's solution (参见下面的计时)但如果您不想输入0和1,那么它会更灵活(参见下面的示例)。

    import numpy as np
    x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
    np.where(x==35, 1, 0)
    

    由此产生

    array([[0, 1, 0, 0],
           [1, 1, 0, 0]])
    

    你可以这样读 如果x等于35,则将其放入1,其他地方插入0 .

    如前所述,您现在有了很大的灵活性,例如,您还可以执行以下操作:

    np.where(x==35, np.sqrt(x), x - 3)
    
    array([[  9.        ,   5.91607978,   9.        ,  23.        ],
           [  5.91607978,   5.91607978,   9.        ,  23.        ]])
    

    所以到处都是 x 等于 35 ,得到平方根,然后从所有其他值中减去 3 .

    时间安排:

    %timeit np.where(x==35, 1, 0)
    100000 loops, best of 3: 5.85 µs per loop
    
    %timeit (x == 35).astype(int)
    100000 loops, best of 3: 3.23 µs per loop
    
    %timeit np.isin(x, 35).astype(int)
    10000 loops, best of 3: 18.7 µs per loop
    
    %timeit (x == 35) + 0
    100000 loops, best of 3: 5.85 µs per loop
    
        5
  •  2
  •   jon331133    8 年前

    如果数组是numpy数组,则可以在数组上使用“==”操作符返回布尔数组。然后使用astype功能将其转换为0和1。

    import numpy as np
    my_array = np.array([[12, 35, 12, 26],
                         [35, 35, 12, 26]])
    
    indexed = (my_array == 35).astype(int)
    
    print indexed
    
        6
  •  2
  •   rth    8 年前

    我喜欢 @yuji approach . 非常优雅!

    为了多样性,这是另一个需要大量劳动的答案。。。。

    >>> from numpy import np
    >>> x = np.array([[12, 35, 12, 26],[35, 35, 12, 26]])
    >>> x
    array([[12, 35, 12, 26],
           [35, 35, 12, 26]])
    >>> y=np.zeros(x.shape)
    >>> y[np.where(x==35)] = np.ones(len(np.where(x==35)[0]))
    >>> y
    array([[ 0.,  1.,  0.,  0.],
           [ 1.,  1.,  0.,  0.]])
    >>>