【问题标题】:how to implement multiple ifelse in numpy如何在numpy中实现多个ifelse
【发布时间】:2020-01-22 16:48:30
【问题描述】:

我有一个这样的数组,需要用 2 替换每 1,用 4 替换每 3,用 1 替换每 4。有没有办法只用 np 而不是循环来做到这一点?

import numpy as np
np.random.seed(2)
arr=np.random.randint(1,5,(3,3),int)
arr

array([[1, 4, 2],
       [1, 3, 4],
       [3, 4, 1]])

如果我按顺序使用数组掩码,它不会给出预期的结果:

array([[2, 1, 2], 
       [2, 4, 1],
       [4, 1, 2]]) 

它基于条件逻辑而不是数学公式

【问题讨论】:

  • 我会为每个替换使用单独的掩码。您应该注意作业的顺序。如果您仍需要帮助,请出示您尝试过的代码。
  • 更好的是,从原始数组创建掩码,而不是在每次修改之后。

标签: python numpy if-statement numpy-ndarray


【解决方案1】:

如果数组值不必介于 1 和 4 之间,您可以使用 np.select

import numpy as np

a = np.random.randint(1,5, (3,3))


condlist = [np.logical_or(a==1, a==2),  a==3, a==4]
choicelist= [2, 4, 1]
b = np.select(condlist, choicelist) 

不关心条件的顺序

【讨论】:

    【解决方案2】:

    这里有一个np.searchsorted 以提高性能 -

    def map_values(arr, old_val, new_val):
        sidx = old_val.argsort()
        idx = np.searchsorted(old_val,arr,sorter=sidx)
        return np.where(old_val[idx]==arr, new_val[sidx[idx]], arr)
    

    示例运行 -

    In [40]: arr
    Out[40]: 
    array([[1, 4, 2],
           [1, 3, 4],
           [3, 4, 1]])
    
    In [41]: old_val = np.array([1,3,4])
        ...: new_val = np.array([2,4,1])
    
    In [42]: map_values(arr, old_val, new_val)
    Out[42]: 
    array([[2, 1, 2],
           [2, 4, 1],
           [4, 1, 2]])
    

    【讨论】:

      【解决方案3】:

      可以使用 lambda 函数和np.vectorize()

      import numpy as np
      np.random.seed(2)
      arr=np.random.randint(1,5,(3,3),int)
      
      f = lambda x: x%4 + 1 if x in [1,3,4] else x
      vfunc = np.vectorize(f)
      

      用法:

      >>> vfunc(arr)
      array([[2, 1, 2],
             [2, 4, 1],
             [4, 1, 2]])
      

      【讨论】:

        【解决方案4】:

        您必须注意分配的顺序。例如,如果你这样做

        arr[arr == 4] = 1
        arr[arr == 1] = 2
        

        现在所有最初为 4 的元素都将是 2,而不是您想要的 1

        一种解决方案是仔细制定作业的顺序:

        arr[arr == 1] = 2
        arr[arr == 4] = 1
        

        但是,这非常脆弱,并且会随着您引入更多它们而分崩离析。最好从原始数组预先创建掩码:

        ones = arr == 1
        fours = arr == 4
        arr[ones] = 2
        arr[fours] = 1
        

        现在分配的顺序无关紧要,因为掩码是在修改数组之前确定的。

        【讨论】:

          【解决方案5】:

          你想要arr % 4 + 1,除了 2 的情况,它保持不变。所以使用 np.where 找到所有的 2。然后做arr % 4 + 1,然后重置所有的2s。

          import numpy as np
          
          np.random.seed(2)
          arr=np.random.randint(1,5,(3,3),int)
          
          twos = np.where(arr == 2)
          arr = arr % 4 + 1
          arr[twos] = 2
          print(arr)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-11-13
            • 1970-01-01
            • 2014-07-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-24
            相关资源
            最近更新 更多