python在由向量组成的多维数组中成对减去两个元素

python在由向量组成的多维数组中成对减去两个元素,python,numpy,multidimensional-array,scipy,subtraction,Python,Numpy,Multidimensional Array,Scipy,Subtraction,我想知道是否有非常简单的方法来计算多维数组中两个元素的两两减法,该数组由使用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]]) 我想得到以下信息: >>>> re

我想知道是否有非常简单的方法来计算多维数组中两个元素的两两减法,该数组由使用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)中预定义函数的非常简单的代码版本

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

方法#1

获取成对索引,将其索引为
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

这不是使用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,])

我很惊讶,也很高兴看到这种创造性的方法。这就是我想要的答案谢谢你的解决方案。是的,很简单,但我想用不同的方式思考。