【问题标题】:Conditional maths operation on 2D numpy array checking on one dimension and doing different operations on diff dimensions2D numpy 数组上的条件数学运算检查一维并在不同维度上执行不同的操作
【发布时间】:2015-08-14 08:46:16
【问题描述】:

我有一个 2D numpy 数组,其中第 0 列是设备的平移旋转,第 1 列是倾斜旋转。每一行都是不同的夹具。我想在每一行上运行以下逻辑:

if(pantilt[0] > 90):
    pantilt[0] -=180
    pantilt[1] *= -1
elif pantilt[0] < -90:
    pantilt[0] += 180
    pantilt[1] *= -1

我了解 1D 上的基本条件操作,例如 myarray[condition] = something。但我无法将其推断为更多维度。

【问题讨论】:

    标签: python arrays numpy multidimensional-array vectorization


    【解决方案1】:

    我会计算一个掩码或布尔索引,并为每一列使用 if:

    构造一个样本数组:

    pantilt=np.column_stack([np.linspace(-180,180,11),np.linspace(0,90,11)])
    
    I = pantilt[:,0]>90
    # J = pantilt[:,0]<-90 
    pantilt[I,0] -= 180
    pantilt[I,1] *= -1
    
    I = pantilt[:,0]<-90  # could use J instead
    pantilt[I,0] += 180
    pantilt[I,1] *= -1
    

    之前:

    array([[-180.,    0.],
           [-144.,    9.],
           [-108.,   18.],
           [ -72.,   27.],
           [ -36.,   36.],
           [   0.,   45.],
           [  36.,   54.],
           [  72.,   63.],
           [ 108.,   72.],
           [ 144.,   81.],
           [ 180.,   90.]])
    

    之后:

    array([[  0.,  -0.],
           [ 36.,  -9.],
           [ 72., -18.],
           [-72.,  27.],
           [-36.,  36.],
           [  0.,  45.],
           [ 36.,  54.],
           [ 72.,  63.],
           [-72., -72.],
           [-36., -81.],
           [  0., -90.]])
    

    如果列是单独的一维数组,这也同样有效。

    【讨论】:

      【解决方案2】:

      这个怎么样:

      pantilt[:,0][pantilt[:,0]>90] -= 180
      pantilt[:,1][pantilt[:,0]>90] *= -1
      pantilt[:,0][pantilt[:,0]<-90] += 180
      pantilt[:,1][pantilt[:,0]<-90] *= -1
      

      【讨论】:

      • 哇,这看起来比我想象的要简单得多!我没有想到要检查两次。虽然我认为应该交换索引并且更复杂一点?在我编写的简单代码(即内核)中,我的 pantilt[0] 是平移,而 pantilt[1] 是倾斜的。当向量化到表 pantilt_array[0] 将返回第一个 pantilt 条目,而不是第一列?同样在做检​​查的时候,不应该是 pantilt_array[:, 0]>90 吗?
      • 是的,你说得对,很好,我已经编辑了我的答案(我实际上不习惯直接使用 numpy 数组;我通常使用 pandas 以便列有名称)跨度>
      • 实际上,我认为这也行不通!因为一旦覆盖第一列,第二个条件就会失败!所以你需要最后做一个。我也不懂 [,][] 语法。在 [] 中使用逗号与 [][] 不一样吗?在 [] 和附加的 [] 中使用逗号是什么意思?
      • 我认为没关系:[pantilt[:,0]&gt;90] 是一个索引器,即一个布尔数组,它选择条件为真的行。所以只有那些行被更新。而[:,0] 是一个列切片器,所以它返回整个第一列。
      【解决方案3】:

      this another related answer 的启发,可以分三步使用masking,而不是像其他两个解决方案中建议的四步,像这样 -

      import numpy as np
      
      # Get mask correspindig to IF conditional statements in original code
      mask_lt = pantilt[:,0]<-90
      mask_gt = pantilt[:,0]>90
      
      # Edit the first column as per the statements in original code
      pantilt[:,0][mask_gt] -= 180
      pantilt[:,0][mask_lt] += 180
      
      # Edit the second column as per the statements in original code
      pantilt[ mask_lt | mask_gt,1] *= -1
      

      运行时测试

      快速运行时测试以比较目前列出的三种方法 -

      In [530]: num_samples = 10000
           ...: org = np.random.randint(-180,180,(num_samples,2))
           ...: 
      
      In [531]: pantilt = org.copy()
      
      In [532]: %timeit hpaulj_mask4(pantilt)
      10000 loops, best of 3: 27.7 µs per loop
      
      In [533]: pantilt = org.copy()
      
      In [534]: %timeit maxymoo_mask4(pantilt)
      10000 loops, best of 3: 33.7 µs per loop
      
      In [535]: pantilt = org.copy()
      
      In [536]: %timeit mask3(pantilt) # three-step masking approach from this solution
      10000 loops, best of 3: 22.1 µs per loop
      

      【讨论】:

        猜你喜欢
        • 2015-12-16
        • 1970-01-01
        • 1970-01-01
        • 2015-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-09
        相关资源
        最近更新 更多