方法#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