计算 Python 中每个元素对之间函数平均值的最有效方法?

Most efficient way to calculate the average of a function between pairs for each element in Python?

问题:

您可以求和,减去对角线,然后除以 M-1:

meanDistance = (np.sum(xij, axis = -1) - np.diagonal(xij, axis1=-2, axis2=-1))  / (M - 1)

演示结果:

(sum-diag) / (M-1):
  time in seconds: 0.03786587715148926
  t=0 first three means: [5.42617836 5.03198446 5.67675881]

nanmean:
  time in seconds: 0.18410110473632812
  t=0 first three means: [5.42617836 5.03198446 5.67675881]

演示代码(Try it online!):

import numpy as np
from time import time

N  = 10**7
M = 10
xij = np.random.uniform(0, 10, N).reshape(int(N/M**2), M, M)

print('(sum-diag) / (M-1):')
t0 = time()
meanDistance = (np.sum(xij, axis = -1) - np.diagonal(xij, axis1=-2, axis2=-1))  / (M - 1)
print('  time in seconds:', time() - t0)
print('  t=0 first three means:', meanDistance[0,:3])

print()
print('nanmean:')
t0 = time()
xij[...,np.arange(M), np.arange(M)] = np.nan
meanDistance = np.nanmean(xij, axis = -1)
print('  time in seconds:', time() - t0)
print('  t=0 first three means:', meanDistance[0,:3])

编辑:我错误地认为需要先计算距离。 这似乎是与 numpy.triu_indices 一起进行的重塑练习。如果距离 x[i,j] != x[j,i] 你需要与 triu_indices & tril_indices.

组合

我假设 x[i,j] = x[j,i],而不是:

import numpy as np

N = 10000
xij = np.random.uniform(0, 10, (N,N))
np.mean( xij[ np.tril_indices(N, k=1) ] )

如果有次元时间,喜欢

N  = 10**5
M = 10
xij = np.random.uniform(0, 10, N).reshape(int(N/M**2), M, M)

你可以

N_dim = xij.shape[-1]

[ np.mean( xij[t,:][np.tril_indices(N_dim, k=1)] ) for t in range(xij.shape[0]) ]

获取均值列表,或总均值

N_dim = xij.shape[-1]

np.mean( [ np.mean( xij[t,:][np.tril_indices(N_dim, k=1)] ) for t in range(xij.shape[0]) ] )

这不是您问题的直接答案,因为它不仅计算对之间的平均距离,而且同时进行距离计算和平均。

假设

  • 对之间的欧氏距离
  • 距离计算基于一个数组,对角线元素为零
  • points是一个轴对应(time, element, coordinate of the position)
  • 的数组

代码

import numpy as np
import numba as nb

@nb.njit(fastmath=True,inline="never")
def mean_dist_inner(points,res):
    div=1/(points.shape[0]-1)

    for i in range(points.shape[0]):
        acc=0
        for j in range(points.shape[0]):
            dist=0
            for k in range(points.shape[1]):
                dist+=(points[i,k]-points[j,k])**2
            acc+=np.sqrt(dist)
        res[i]=acc*div
    return

@nb.njit(fastmath=True,parallel=True,cache=True)
def mean_dist_time(points):

    res=np.empty((points.shape[0],points.shape[1]),dtype=np.float64)

    for t in nb.prange(points.shape[0]):
        mean_dist_inner(points[t],res[t])
    return res

时机

points=np.random.rand(10000,40,40)
%timeit mean_dist_time(points)
#40.1 ms ± 9.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)