我有数据阵列,形状为100x100。我想把它分成5x5块,每个块有20x20网格。我想要的每个块的值是其中所有值的总和。
有更优雅的方式来实现它吗?
x = np.arange(100)
y = np.arange(100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
Z_new = np.zeros((5, 5))
for i in range(5):
for j in range(5):
Z_new[i, j] = np.sum(Z[i*20:20+i*20, j*20:20+j*20])
这是基于索引,如果基于x?
x = np.linspace(0, 1, 100)
y = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
x_new = np.linspace(0, 1, 15)
y_new = np.linspace(0, 1, 15)
Z_new?
答案 0 :(得分:2)
只需reshape
将这两个轴中的每一个分成两个,每个轴形状为(5,20)
,形成一个4D
数组,然后沿长度为20
的轴求和,像这样 -
Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3))
与np.einsum
-
Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20))
通用块大小
扩展到一般情况 -
H,W = 5,5 # block-size
m,n = Z.shape
Z_new = Z.reshape(H,m//H,W,n//W).sum(axis=(1,3))
einsum
成为 -
Z_new = np.einsum('ijkl->ik',Z.reshape(H,m//H,W,n//W))
要计算块的平均值/平均值,请使用mean
代替sum
方法。
通用块大小和缩减操作
扩展为使用ufuncs
支持多个reduction
参数和axes
进行缩减的axis
操作,它将是 -
def blockwise_reduction(a, height, width, reduction_func=np.sum):
m,n = a.shape
a4D = a.reshape(height,m//height,width,n//width)
return reduction_func(a4D,axis=(1,3))
因此,为了解决我们的具体情况,它将是:
blockwise_reduction(Z, height=5, width=5)
对于逐块平均计算,它将是 -
blockwise_reduction(Z, height=5, width=5, reduction_func=np.mean)
答案 1 :(得分:0)
您可以执行以下操作。
t = np.eye(5).repeat(20, axis=1)
Z_new = t.dot(Z).dot(t.T)
这是正确的,因为Z_new[i, j] = t[i, k] * Z[k, l] * t[j, l]
此外,这似乎比Divakar的解决方案更快。
答案 2 :(得分:0)
这样的问题是像scipy.ndimage.measurements.sum这样的函数的一个非常好的候选者,因为它允许"分组"和"标签"条款。你会得到你想要的东西:
labels = [[20*(y//5) + x//5 for x in range(100)] for y in range(100)]
s = scipy.ndimage.measurements.sum(Z, labels, range(400))
(未经测试,但这是个主意)。