【问题标题】:Having multiple equality conditionals for numpy arraysnumpy 数组有多个相等条件
【发布时间】:2017-07-06 08:15:34
【问题描述】:

假设我有一个大型 2D numpy 数组(称为 A),其中包含从 0 到 9 的整数。

我正在尝试编写一个函数,它返回一个与 A 形状相同的二进制 numpy 数组(称为 B),具有以下功能。

如果A中的对应元素出现在给定列表L中,则B中的条目为1;否则,该条目为零。

下面显示了可能不是最有效的代码。

A = np.random.randint(0, 10, (5, 5))
L = [3,4,5]

B = np.zeros(A.shape)
for e in L:
    B[A==e] = 1

有没有更快的方法?

谢谢!

【问题讨论】:

    标签: python arrays numpy matrix conditional-statements


    【解决方案1】:

    看来我有责任指出显而易见的事情:

    def AinL(A, L):
        B = np.zeros((10,), int)
        B[L] = 1
        return B[A]
    

    基准测试:

     10x10 #L=3
    orig     0.6665631101932377
    HAL      0.4370500799268484
    Psidom   1.13961720908992
    PP       0.23527960386127234
    
     100x100 #L=3
    orig     0.3015591569710523
    HAL      0.29902734607458115
    Psidom   0.4470538650639355
    PP       0.18963343487121165
    
     1000x1000 #L=4
    orig     0.5516874771565199
    HAL      0.5967503408901393
    Psidom   0.6331975681241602
    PP       0.23225238709710538
    
     10000x1000 #L=2
    orig     0.8539429588709027
    HAL      0.9840140701271594
    Psidom   1.0392512339167297
    PP       0.7203555379528552
    

    【讨论】:

      【解决方案2】:

      这里有两个numpy 选项和np.in1d,它是来自基本python 的in 的矢量化版本。当数组很大时,第一个选项显示一些加速:

      选项一(快一)

      np.in1d(A, L).reshape(A.shape).astype(int)
      

      选项二(慢一)

      np.apply_along_axis(np.in1d, 0, A, L).astype(int)
      

      时间

      A = np.random.randint(0, 10, (1000, 1000))
      L = [3,4,5]
      ​
      def loop():
          B = np.zeros(A.shape)
          for e in L:
              B[A==e] = 1
          return B
      
      %timeit np.in1d(A, L).reshape(A.shape).astype(int)
      # 100 loops, best of 3: 6.4 ms per loop
      
      %timeit loop()
      # 100 loops, best of 3: 16.8 ms per loop
      
      %timeit np.apply_along_axis(np.in1d, 1, A, L).astype(int)
      # 10 loops, best of 3: 21.5 ms per loop
      
      %timeit np.apply_along_axis(np.in1d, 0, A, L).astype(int)
      # 10 loops, best of 3: 35.1 ms per loop
      

      结果检查

      B1 = loop()
      B2 = np.apply_along_axis(np.in1d, 0, A, L).astype(int)
      B3 = np.apply_along_axis(np.in1d, 1, A, L).astype(int)
      B4 = np.in1d(A, arrL).reshape(A.shape).astype(int)
      
      (B1 == B2).all()
      # True
      
      (B1 == B3).all()
      # True
      
      (B1 == B4).all()
      # True
      

      【讨论】:

      • 我的计时结果提供了不同的叙述。我正在使用来自 anaconda 的 python 3.5 和 numpy 1.10.4,原始循环比使用 in1d 快大约 3 倍。编辑:我现在看到您使用了 1000x1000 随机矩阵。我将使用相同大小的矩阵重新测试。
      • @HAL9001 我也刚刚在 python 3 上进行了测试,我得到了非常一致的结果。第一个 np.in1d 选项更快。您要测试的阵列有多大?
      • Psidom 的结果在使用 1000x1000 时得到确认。
      【解决方案3】:

      使用@Psidom的1000x1000矩阵,我介绍了另外两种方法,包括@Psidom提供的np.in1d方法。

      一个使用迭代求和,另一个使用迭代按位或。

      按位迭代或trial2() 在下面证明了自己,提供的结果大约比原始结果快 4 倍,比 numpy 的 in3d 快 2 倍,但请注意,它提供的矩阵结果是布尔类型.

      当bitwise方法修改为返回整数结果trial2_int()时,其速度基本相当于numpy的in1d

      A = np.random.randint(0,10,(1000,1000))
      L = [3,4,5]
      def original():
        B = np.zeros(A.shape)
        for e in L:
            B[A==e] = 1
        return B
      
      def trial1():
        B = np.empty(A.shape)
        for e in L:
          B += A == e
        return B
      
      def trial2():
        B = A==L[0]
        for e in L[1:]:
          B |= A == e
        return B
      
      def trial2_int():
        B = trial2()
        return B.astype(int)
      
      def trial_Psidom():
        B = np.in1d(A,L).reshape(A.shape).astype(int)
        return B
      

      结果:

      %timeit original()
      # 100 loops, best of 3: 10.5 ms per loop
      %timeit trial1()
      # 100 loops, best of 3: 9.43 ms per loop
      %timeit trial2()
      # 100 loops, best of 3: 2.37 ms per loop
      %timeit trial2_int()
      # 100 loops, best of 3: 5.31 ms per loop
      %timeit trial_Psidom()
      # 100 loops, best of 3: 5.37 ms per loop    
      

      【讨论】:

      • 如果L 相对于A 较小,np.in1d 会为您的trial2 提供一个解构版本 - 迭代L 并使用B|=...
      猜你喜欢
      • 2020-09-11
      • 2014-10-18
      • 2015-10-20
      • 2022-01-23
      • 2021-06-17
      • 2019-05-17
      • 1970-01-01
      • 2020-10-02
      相关资源
      最近更新 更多