【问题标题】:python pairwise subtract two elements in multi-dimensional array consisted of vectorspython成对减去由向量组成的多维数组中的两个元素
【发布时间】:2018-02-22 19:13:22
【问题描述】:

我想知道是否有非常简单的方法可以使用 NUMPY 或 SCIPY 库中的函数来计算由向量组成的多维数组中两个元素的成对减法。

让我介绍一个例子:

>>> a = (np.arange(9)).reshape((3,3)) # a list of 3 vectors (x, y, z)

>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

我想得到以下内容:

>>>> result
array([[3,3,3],
       [6,6,6],
       [3,3,3]])
# first element comes from [3,4,5] - [0,1,2]
# second element comes from [6,7,8] - [0,1,2]
# third element comes from [6,7,8] - [3,4,5]

我不关心结果上的符号 (+/-),这取决于两个向量的减法顺序。 但是,我想知道使用 Scipy 或 Numpy 库(如 scipy.spatial.distance.pdist)中预定义函数的非常简单的代码版本。

我确实需要循环代码来逐个元素地迭代结果, 相反,我只需要一行就可以得到结果。

【问题讨论】:

    标签: python numpy multidimensional-array scipy subtraction


    【解决方案1】:

    方法#1

    使用np.triu_indices 获取成对索引,用这些索引到a 的行中并计算差异 -

    In [8]: r,c = np.triu_indices(len(a),1)
    
    In [9]: a[c] - a[r]
    Out[9]: 
    array([[3, 3, 3],
           [6, 6, 6],
           [3, 3, 3]])
    

    方法 #2

    我们还可以使用切片来避免创建索引,而索引部分本身会为减法所需的切片创建输入数组的副本。因此,我们将只使用视图,但我们需要在该过程中进行迭代。正如我们稍后将在时序中验证的那样,切片的优势在大型阵列上表现出来。实施将是 -

    n = len(a)
    N = n*(n-1)//2
    idx = np.concatenate(( [0], np.arange(n-1,0,-1).cumsum() ))
    start, stop = idx[:-1], idx[1:]
    out = np.empty((N,a.shape[1]),dtype=a.dtype)
    for j,i in enumerate(range(n-1)):
        out[start[j]:stop[j]] = a[i+1:] - a[i,None]
    

    运行时测试

    方法作为函数 -

    def pairwise_row_diff_triu_indices(a):
        r,c = np.triu_indices(len(a),1)
        out = a[c] - a[r]
        return out
    
    def pairwise_row_diff_slicing(a):
        n = len(a)
        N = n*(n-1)//2
        idx = np.concatenate(( [0], np.arange(n-1,0,-1).cumsum() ))
        start, stop = idx[:-1], idx[1:]
        out = np.empty((N,a.shape[1]),dtype=a.dtype)
        for j,i in enumerate(range(n-1)):
            out[start[j]:stop[j]] = a[i+1:] - a[i,None]
        return out
    

    时间安排 -

    In [53]: np.random.seed(0)
    
    In [54]: a = np.random.randint(0,9,(1000,3))
    
    In [55]: %timeit pairwise_row_diff_triu_indices(a)
        ...: %timeit pairwise_row_diff_slicing(a)
    10 loops, best of 3: 21 ms per loop
    100 loops, best of 3: 6.01 ms per loop
    
    In [56]: a = np.random.randint(0,9,(5000,3))
    
    In [57]: %timeit pairwise_row_diff_triu_indices(a)
        ...: %timeit pairwise_row_diff_slicing(a)
    1 loop, best of 3: 456 ms per loop
    10 loops, best of 3: 110 ms per loop
    

    【讨论】:

    • 我很惊讶,也很高兴看到这样的创意方法。这就是我想要的答案
    【解决方案2】:

    这不是使用 numpy 或 scipy 函数...但它是一个简单的解决方案

    length = a.shape[1]
    new_arr = []
    for ii in range(length):
        for jj in range(ii+1,length):
            new_arr.append(a[ii,]-a[jj,])
    

    【讨论】:

    • 感谢您的解决方案。是的,这很简单,但我想以不同的方式思考。
    猜你喜欢
    • 1970-01-01
    • 2021-02-11
    • 2018-12-13
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2019-01-23
    • 1970-01-01
    相关资源
    最近更新 更多