如何计算沿其中一个维度的 3d 体积的非零元素的平均值
How to compute mean for non zero elements of a 3d volume along one of the dimensions
我有一个 3d 体积 DxHxW
,我只想计算 D
维度上非零值的平均值,以获得每个元素的 2d HxW
平均值.这是我当前的实现,将所有内容设置为 nan
,然后计算 nanmean
。但是,它很慢,在 Python 中是否有更好的方法来做到这一点?
volume_3d[volume_3d == 0] = np.nan
mean_2d = np.nanmean(volume_3d, 0))
mean_2d[np.isnan(mean_2d)] = 0
我将测试数组创建为:
D = 2; H = 3; W = 4
volume_3d = np.arange(1, D * H * W + 1, dtype=float).reshape(D, W, H)
volume_3d[0, 1, 0] = volume_3d[0, 2, 1] = volume_3d[1, 2, 1] = 0
其实为了不改变源数组,你原来的代码
可以重写为以下函数:
def f1(arr):
wrk = np.copy(arr)
wrk[wrk == 0] = np.nan
mean_2d = np.nanmean(wrk, 0)
mean_2d[np.isnan(mean_2d)] = 0
return mean_2d
要获得结果,您可以 运行 res1 = f1(volume_3d)
结果是:
array([[ 7., 8., 9.],
[16., 11., 12.],
[13., 0., 15.],
[16., 17., 18.]])
我的建议是如何更快地计算出这个结果:
def f2(arr):
cnt = np.sum(arr != 0, axis=0)
tot = np.sum(arr, axis=0)
return np.divide(tot, cnt, out=np.zeros_like(tot), where=cnt!=0)
使用 %timeit 我比较了执行时间:
- 您的代码:330 µs,
- 我的代码:160 µs,
即我的代码运行速度快了 2 倍。
另一个值得一提的细节是您的代码引发了 RuntimeWarning:
空切片的平均值 和我的 运行s 没有警告。
我想对于更大的阵列,差异应该更明显。
自己试试。
我有一个 3d 体积 DxHxW
,我只想计算 D
维度上非零值的平均值,以获得每个元素的 2d HxW
平均值.这是我当前的实现,将所有内容设置为 nan
,然后计算 nanmean
。但是,它很慢,在 Python 中是否有更好的方法来做到这一点?
volume_3d[volume_3d == 0] = np.nan
mean_2d = np.nanmean(volume_3d, 0))
mean_2d[np.isnan(mean_2d)] = 0
我将测试数组创建为:
D = 2; H = 3; W = 4
volume_3d = np.arange(1, D * H * W + 1, dtype=float).reshape(D, W, H)
volume_3d[0, 1, 0] = volume_3d[0, 2, 1] = volume_3d[1, 2, 1] = 0
其实为了不改变源数组,你原来的代码 可以重写为以下函数:
def f1(arr):
wrk = np.copy(arr)
wrk[wrk == 0] = np.nan
mean_2d = np.nanmean(wrk, 0)
mean_2d[np.isnan(mean_2d)] = 0
return mean_2d
要获得结果,您可以 运行 res1 = f1(volume_3d)
结果是:
array([[ 7., 8., 9.],
[16., 11., 12.],
[13., 0., 15.],
[16., 17., 18.]])
我的建议是如何更快地计算出这个结果:
def f2(arr):
cnt = np.sum(arr != 0, axis=0)
tot = np.sum(arr, axis=0)
return np.divide(tot, cnt, out=np.zeros_like(tot), where=cnt!=0)
使用 %timeit 我比较了执行时间:
- 您的代码:330 µs,
- 我的代码:160 µs,
即我的代码运行速度快了 2 倍。
另一个值得一提的细节是您的代码引发了 RuntimeWarning: 空切片的平均值 和我的 运行s 没有警告。
我想对于更大的阵列,差异应该更明显。 自己试试。