【问题标题】:Change 1's to 0 and 0's to 1 in numpy array without looping在 numpy 数组中将 1 更改为 0 并将 0 更改为 1 而无需循环
【发布时间】:2019-10-28 21:07:38
【问题描述】:

假设我有一个 numpy 数组,我想将所有 1 交换为 0,将所有 0 交换为 1(该数组将具有其他值,并且 0 和 1 没有什么特别之处)。当然,我可以循环遍历数组并逐个更改它。您可以推荐使用一种有效的方法吗? np.where() 方法有这个操作的选项吗?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    最棘手的部分是the array will have other values。如果只有 0 和 1(没有其他值),arr = ~arr + 2 是最快的方法。如果需要考虑the array will have other values,请使用arr^(arr&1==arr)。这是基准。

    %%timeit
    
    np.random.seed(0)
    arr = np.random.randint(0,2,100)
    
    arr = ~arr + 2
    
    38.8 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %%timeit
    
    np.random.seed(0)
    arr = np.random.randint(0,2,100)
    
    where_1 = arr == 1
    where_0 = arr == 0
    
    arr[where_1] = 0 # replacing 1s with 0s
    arr[where_0] = 1 # replacing 0s with 1s
    
    45.2 µs ± 7.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %%timeit
    
    np.random.seed(0)
    arr = np.random.randint(0,2,100)
    
    arr = arr^(arr&1==arr)
    
    40.3 µs ± 7.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %%timeit
    
    np.random.seed(0)
    arr = np.random.randint(0,2,100)
    
    where_1 = np.where(arr == 1)
    where_0 = np.where(arr == 0)
    
    arr[where_0] = 1
    arr[where_1] = 0
    
    49.1 µs ± 13.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %%timeit
    
    np.random.seed(0)
    arr = np.random.randint(0,2,100)
    
    arr = np.where((arr==0)|(arr==1), arr^1, arr)
    
    52.3 µs ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    【讨论】:

      【解决方案2】:

      inverted = ~arr + 2,因为我的数组是 8 位的,所以对我有用

      “~”运算符将数组中整数的所有位从 0 翻转到 1,反之亦然。例如,如果你有一个用八位(一个字节)0000 0000 表示的整数 0,波浪号运算 ~0000 0000 会得到值 1111 1111,即整数值 -1,reference

      所以如果 a = 0,~a 给出 -1 并且 (~a+2) 给出 1 如果 a = 1,~a 给出 -2 并且 (~a+2) 给出 0

      【讨论】:

        【解决方案3】:

        iverted = ~arr + 2 应该做的工作

        【讨论】:

        • 请注意,此答案无法处理the array will have other values。例如,4 将是 -3
        【解决方案4】:
        a^(a&1==a)
        

        例如

        a = np.arange(-3, 4)
        a^(a&1==a)
        # array([-3, -2, -1,  1,  0,  2,  3])
        

        【讨论】:

        • 哈!好吧,这很整洁!不得不跑自己去理解(a&1==a)在这里做了什么:)
        • @yatu 是的,这里知道运算符优先级的人不能太多。我当然不得不反复试验;-]
        • 我喜欢这个。我总是更喜欢计算结果而不是 if / else。
        • 太棒了!可能不是最符合语义的,但绝对是最优化的。
        • 最好的方法。请投票赞成这个答案。基准见my answer
        【解决方案5】:

        一种不需要使用任何特殊方法(例如np.where())的非常简单的方法是获取numpy数组中变量条件的索引,并相应地分配所需的值(在您的情况下0 用于1s1 用于0s) 到数组中的相应位置项。这也适用于 0s1s 以外的值。此外,您不需要任何临时变量来交换值。

        import numpy as np
        arr = np.array([1, 0, 2, 3, 6, 1, 0])
        indices_one = arr == 1
        indices_zero = arr == 0
        arr[indices_one] = 0 # replacing 1s with 0s
        arr[indices_zero] = 1 # replacing 0s with 1s
        
        Output: array([0, 1, 2, 3, 6, 0, 1])
        

        【讨论】:

        • 读者注意:以下更好(更快、更通用)的解决方案
        【解决方案6】:

        这是使用np.where 的一种方法,当它是01 时,取给定值的按位XOR

        np.where((a==0)|(a==1), a^1, a)
        

        例如:

        a = np.array([[0,1,2,1], [1,2,0,3]])
        print(a)
        array([[0, 1, 2, 1],
               [1, 2, 0, 3]])
        
        np.where((a==0)|(a==1), a^1, a)
        
        array([[1, 0, 2, 0],
               [0, 2, 1, 3]])
        

        【讨论】:

        • a^1 太聪明了:-)
        • 参考stackoverflow.com/questions/2451386/… 给那些(像我一样!)不知道^ 做什么的人...
        • 顺便说一句,你也可以使用1-a
        • 如果数组是无符号整数,那么您的 2 个测试可能会通过单个测试 a<2 变得更简单/更快,顺便说一句 ;-)
        • 是的,在这种情况下,这将是一个很好的简化 :) @MarkSetchell
        【解决方案7】:

        对于 np.where,这是一个不太聪明的选择,只是将它用于索引:

        where_0 = np.where(arr == 0)
        where_1 = np.where(arr == 1)
        
        arr[where_0] = 1
        arr[where_1] = 0
        

        如果您对其他值有更多了解(例如,它们都是小数字),可能会有更多选择,但这是最简单的。

        【讨论】:

        • 也许除了使用两次np.where之外,您还可以使用np.select
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多