我想在步骤
d
的规则网格上对大小为NxNx...xN(d次)的M
维数组k
进行平均,即构建一个大小为NxNx的新数组N
.. .xN (d 次) 其中,在步骤 k 的正则网格的每个超立方体 H 中,数组的值都相同,并且等于原始数组中 H 的平均值。
更清楚地举例,对于
d=2
、N=4
和 k=2
:
M=[[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
和
N=[[1.5,1.5,3.5,3.5],[1.5,1.5,3.5,3.5],[1.5,1.5,3.5,3.5],[1.5,1.5,3.5,3.5]]
这与现有问题相关:按平均值分组 2D numpy 数组 然而,这仅适用于 2D 数组,并不能完全输出我想要的形状的数组。
我尝试在 d=2 的情况下自己实现它,但对更高维度进行类似的操作将意味着重复 d 次循环,这似乎令人望而却步(我不知道如何做到这一点)。我确信有一种更紧凑、更有效的方法可以做到这一点。 我对 d=2 的尝试:
def local_average_img(M,k):
l=len(M[0])
N = np.zeros((l,l))
for x in range(l):
for y in range(l):
print(np.mean(M[(x//k)*k:(x//k)*k+k, (y//k)*k:(y//k)*k+k]))
N[x][y]=np.mean(M[(x//k)*k:(x//k)*k+k, (y//k)*k:(y//k)*k+k])
return(N)
M = np.array([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]])
k = 2
result = local_average_img(M, k)
print(result)
以下解决方案可以帮助您。正如你所看到的,你并没有摆脱所有的循环(我想说你不能,但人可以梦想)。优点是“重循环”是为了计算索引并形成切片而完成的。然后,实际平均在
numpy
中完成,这比嵌套 for
循环更快。
import itertools
import numpy as np
d = 2 # number of dimensions
n = 4 # size of each dimension
k = 2 # side of the hypercube to average in
# Define M input hypercube and initialize "empty" H hypercube
M = (np.random.rand(*[n for i in range(d)]) * 10).astype(int)
H = np.zeros(M.shape, dtype=np.float32)
# Compute the index of the first element in each sub-hypercube.
# In the 2D example, it is the top-left corner of the "square".
indexes = [i for i in range(n)
if i % d == 0]
indexes = itertools.product(indexes, repeat = d)
for idx in indexes:
# Also compute the index of the last element of the sub-hypercube.
# In the 2D example, it is the bottom-right corner of the "square".
idx_i = np.array(idx)
idx_f = idx_i + k
# Define a tuple of slices objects to index the sub-hypercube.
nd_slice = []
for dim in range(d):
s = slice(idx_i[dim], idx_f[dim], 1)
nd_slice.append(s)
nd_slice = tuple(nd_slice)
# Compute the average in the sub-hypercube and substitute it to the current values.
H[nd_slice] = np.mean(M[nd_slice])
print(M)
print(H)