【问题标题】:Python: Insert columns into a numpy array based on maskPython:根据掩码将列插入到numpy数组中
【发布时间】:2022-01-12 09:21:40
【问题描述】:

假设我有以下数据:

mask = [[0, 1, 1, 0, 1]] # 2D mask
ip_array = [[4, 5, 2]
            [3, 2, 1]
            [1, 8, 6]] # 2D array

我想将 0 的列插入到 ip_array 中,只要掩码中有 0。所以输出应该是这样的:

[[0, 4, 5, 0, 2]
 [0, 3, 2, 0, 1]
 [0, 1, 8, 0, 6]]

我是 numpy 函数的新手,我正在寻找一种有效的方法来做到这一点。任何帮助表示赞赏!

【问题讨论】:

  • 高效如何?没有python循环? (仅 numpy 使用?)
  • 我正在尝试使用 numpy 来做到这一点
  • 你的 n 值是多少? (len(mask) 和 len(ip_array)) 平均? (mini 和 maxi?)因为在“设置”时使用 numpy 很耗时,所以有一个阈值,在这个阈值中使用或不使用它是个好主意......
  • 掩码和ndarray的长度会不时变化

标签: python numpy numpy-ndarray mask


【解决方案1】:

这是一种分两步完成的方法:

(i) 创建一个正确形状的零数组(ip_array 的第一个维度和mask 的第二个维度)

(ii) 在第二维上使用mask(作为布尔掩码)并将ip_array 的值分配给零数组。

out = np.zeros((ip_array.shape[0], mask.shape[1])).astype(int)
out[..., mask[0].astype(bool)] = ip_array
print(out)

输出:

[[0 4 5 0 2]
 [0 3 2 0 1]
 [0 1 8 0 6]]

【讨论】:

  • 非常感谢!没想到这么简单:)
【解决方案2】:

这是另一种使用切片的方法,带有 cumsum 掩码和输入中的额外 0 列。 cumsum 掩码将具有ip_array + 1 和 0 的索引,只要添加零。连接数组有一个额外的初始零列,因此使用 0 进行索引会产生一列零。

m = (mask.cumsum()*mask)[0]
# array([0, 1, 2, 0, 3])

np.c_[np.zeros(ip_array.shape[0]), ip_array][:,m].astype(int)

# array([[0, 4, 5, 0, 2],
#        [0, 3, 2, 0, 1],
#        [0, 1, 8, 0, 6]])

【讨论】:

    【解决方案3】:

    带有参数和其他方法的解决方案,而不是绿色检查。所以比较好理解。 只是最后一行对操作很重要。

    import numpy
    import random
    
    n1 = 5
    n2 = 5
    r = 0.7
    random.seed(1)
    a = numpy.array([[0 if random.random() > r else 1 for _ in range(n1)]])
    n3 = numpy.count_nonzero(a)
    b = numpy.array([[random.randint(1,9) for _ in range(n3)] for _ in range(n2)])
    c = numpy.zeros((n2, n1))
    c[:, numpy.where(a)[1]] = b[:]
    

    结果:

    a = array([[1, 0, 0, 1, 1]])
    b = array([[8, 8, 7],
           [4, 2, 8],
           [1, 7, 7],
           [1, 8, 5],
           [4, 2, 6]])
    c = array([[8., 0., 0., 8., 7.],
           [4., 0., 0., 2., 8.],
           [1., 0., 0., 7., 7.],
           [1., 0., 0., 8., 5.],
           [4., 0., 0., 2., 6.]])
    

    您的时间处理取决于 n 值:

    使用此代码:

    import numpy
    import random
    import time
    import matplotlib.pyplot as plt
    
    n1 = 5
    n2 = 5
    r = 0.7
    
    
    def main(n1, n2):
        print()
        print(f"{n1 = }")
        print(f"{n2 = }")
        random.seed(1)
        a = numpy.array([[0 if random.random() > r else 1 for _ in range(n1)]])
        n3 = numpy.count_nonzero(a)
        b = numpy.array([[random.randint(1,9) for _ in range(n3)] for _ in range(n2)])
        t0 = time.time()
        c = numpy.zeros((n2, n1))
        c[:, numpy.where(a)[1]] = b[:]
        t = time.time() - t0
        print(f"{t = }")
        return t
    
    
    t1 = [main(10**i, 10) for i in range(1, 8)]
    t2 = [main(10, 10**i) for i in range(1, 8)]
    
    plt.plot(t1, label="n1 time process evolution")
    plt.plot(t2, label="n2 time process evolution")
    
    plt.xlabel("n-values (log)")
    plt.ylabel("Time processing (s)")
    plt.title("Insert columns into a numpy array based on mask")
    plt.legend()
    plt.show()
    

    【讨论】:

      【解决方案4】:
      mask = np.array([0, 1, 1, 0, 1])
      #extract indices of zeros
      mask_pos = (list(np.where(mask == 0)[0]))
      ip_array =np.array([[4, 5, 2],
              [3, 2, 1],
              [1, 8, 6]])
      
      #insert 0 at respextive mask position
      for i in mask_pos:
          ip_array = np.insert(ip_array,i,0,axis=1)
      
      print(ip_array)
      

      【讨论】:

        猜你喜欢
        • 2016-03-28
        • 2020-02-29
        • 2021-07-04
        • 2013-09-08
        • 1970-01-01
        • 2021-06-24
        • 1970-01-01
        • 2019-06-08
        • 1970-01-01
        相关资源
        最近更新 更多