【问题标题】:Replace elements of a multidimensional numpy array according to a rule根据规则替换多维numpy数组的元素
【发布时间】:2016-07-13 22:00:30
【问题描述】:

假设我们有一个 numpy 数组:

import numpy as np
arr = np.array([[ 5,  9],[14, 23],[26,  4],[ 5, 26]])

我想用它的出现次数替换每个元素,

 unique0, counts0= np.unique(arr.flatten(), return_counts=True)
 print (unique0, counts0)

(数组([ 4, 5, 9, 14, 23, 26]), 数组([1, 2, 1, 1, 1, 2]))

所以 4 应该替换为 1、5 替换为 2 等以获得:

[[ 2, 1],[1, 1],[2, 1],[2, 2]]

有没有办法在 numpy 中实现这一点?

【问题讨论】:

    标签: python arrays numpy multidimensional-array replace


    【解决方案1】:

    使用另一个可选参数 return_inverse 和 np.unique 根据唯一性标记所有元素,然后将它们映射到计数以提供我们想要的输出,就像这样 -

    _, idx, counts0 = np.unique(arr, return_counts=True,return_inverse=True)
    out = counts0[idx].reshape(arr.shape)
    

    示例运行 -

    In [100]: arr
    Out[100]: 
    array([[ 5,  9],
           [14, 23],
           [26,  4],
           [ 5, 26]])
    
    In [101]: _, idx, counts0 = np.unique(arr, return_counts=True,return_inverse=True)
    
    In [102]: counts0[idx].reshape(arr.shape)
    Out[102]: 
    array([[2, 1],
           [1, 1],
           [2, 1],
           [2, 2]])
    

    【讨论】:

      【解决方案2】:

      这是一个替代解决方案,因为@Divakar 的答案在

       In [1]: import numpy as np
      
       In [2]: arr = np.array([[ 5,  9],[14, 23],[26,  4],[ 5, 26]])
      
       In [3]: np.bincount(arr.flatten())[arr]
       Out[3]: 
       array([[2, 1],
              [1, 1],
              [2, 1],
              [2, 2]])
      

      测试速度(使用 10000 个随机整数):

      def replace_unique(arr):
          _, idx, counts0 = np.unique(arr,return_counts=True,return_inverse=True)
          return counts0[idx].reshape(arr.shape)
      
      def replace_bincount(arr):
          return np.bincount(arr.flatten())[arr]
      
      arr = np.random.random_integers(30,size=[10000,2])
      
      
      %timeit -n 1000 replace_bincount(arr)
      # 1000 loops, best of 3: 68.3 µs per loop
      %timeit -n 1000 replace_unique(arr)
      # 1000 loops, best of 3: 922 µs per loop
      

      所以bincount 方法比unique 方法快~14 倍。

      【讨论】:

      • 可爱的替代品!
      • 另外,您可以使用.ravel() 代替.flatten(),这样可以避免复制并提高性能。
      猜你喜欢
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多