【问题标题】:Convert 1D array with coordinates into 2D array in numpy在numpy中将带坐标的一维数组转换为二维数组
【发布时间】:2019-10-21 01:33:07
【问题描述】:

我有一个形状为 (N,) 的值数组 arr 和一个形状为 (N,2) 的坐标数组 coords。我想在 (M,M) 数组grid 中表示它,这样grid 在不在coords 中的坐标处取值 0,并且对于包含的坐标,它应该存储所有值的总和在具有该坐标的arr 中。因此,如果 M=3、arr = np.arange(4)+1coords = np.array([[0,0,1,2],[0,0,2,2]]),那么 grid 应该是:

array([[3., 0., 0.],
       [0., 0., 3.],
       [0., 0., 4.]])

这很重要的原因是我需要能够多次重复此步骤,arr 中的值每次都会改变,坐标也会改变。理想情况下,我正在寻找矢量化解决方案。我怀疑我可能能够以某种方式使用np.where,但目前还不是很明显。

解决方案时间

我已经对此时存在的解决方案进行了计时,并且累加器方法似乎比稀疏矩阵方法稍快,由于 cmets 中解释的原因,第二种累加方法最慢:

%timeit for x in range(100): accumulate_arr(np.random.randint(100,size=(2,10000)),np.random.normal(0,1,10000))
%timeit for x in range(100): accumulate_arr_v2(np.random.randint(100,size=(2,10000)),np.random.normal(0,1,10000))
%timeit for x in range(100): sparse.coo_matrix((np.random.normal(0,1,10000),np.random.randint(100,size=(2,10000))),(100,100)).A
47.3 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
103 ms ± 255 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
48.2 ms ± 36 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

【问题讨论】:

    标签: python arrays numpy vectorization


    【解决方案1】:

    np.bincount -

    def accumulate_arr(coords, arr):
        # Get output array shape
        m,n = coords.max(1)+1
    
        # Get linear indices to be used as IDs with bincount
        lidx = np.ravel_multi_index(coords, (m,n))
        # Or lidx = coords[0]*(coords[1].max()+1) + coords[1]
    
        # Accumulate arr with IDs from lidx
        return np.bincount(lidx,arr,minlength=m*n).reshape(m,n)
    

    示例运行 -

    In [58]: arr
    Out[58]: array([1, 2, 3, 4])
    
    In [59]: coords
    Out[59]: 
    array([[0, 0, 1, 2],
           [0, 0, 2, 2]])
    
    In [60]: accumulate_arr(coords, arr)
    Out[60]: 
    array([[3., 0., 0.],
           [0., 0., 3.],
           [0., 0., 4.]])
    

    另一个np.add.at 在类似的行上,可能更容易理解 -

    def accumulate_arr_v2(coords, arr):
        m,n = coords.max(1)+1
        out = np.zeros((m,n), dtype=arr.dtype)
        np.add.at(out, tuple(coords), arr)
        return out
    

    【讨论】:

    • 到目前为止,我已经尝试为每个答案计时,这里的 v2 似乎要慢一些,可能是因为它每次都会初始化一个新数组。
    • @algol 是 np.add.at 减慢了速度。使用bincount,它总是更快。
    【解决方案2】:

    一种方法是创建一个sparse.coo_matrix 并将其转换为密集:

    from scipy import sparse
    sparse.coo_matrix((arr,coords),(M,M)).A
    # array([[3, 0, 0],
    #        [0, 0, 3],
    #        [0, 0, 4]])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-16
      • 2023-02-03
      • 2021-06-28
      • 2016-02-18
      • 2018-02-19
      相关资源
      最近更新 更多