Numpy多轴同时聚合:将三维数组从(27,27,27)压缩至(9,9,9)
解决Numpy三维数组按3×3×3块取均值的问题
原代码错误原因
你写的mean_over函数没有返回值,默认返回None,这才导致apply_over_axes抛出AttributeError: 'NoneType' object has no attribute 'ndim'错误。另外,np.apply_over_axes确实是依次对每个轴单独做均值计算,不过数学上,先对轴0每3个取均值,再对轴1、轴2做同样操作,最终结果和直接计算3×3×3块的均值是一致的,但这种实现方式效率很低,不如直接用数组变形+均值的方法。
推荐实现方法(简洁高效)
最直接的方式是通过reshape将原数组的每个轴拆分为「块数×块大小」的结构,然后直接对块大小对应的轴取均值:
import numpy as np # 假设the_array是形状为(27,27,27)的numpy数组 block_size = 3 # 构造新形状:(9,3,9,3,9,3) new_shape = (the_array.shape[0]//block_size, block_size, the_array.shape[1]//block_size, block_size, the_array.shape[2]//block_size, block_size) # 变形后对所有块大小的轴取均值,得到(9,9,9)的数组 the_array_small = the_array.reshape(new_shape).mean(axis=(1,3,5))
如果要写得更通用(适配任意维度、任意块大小,只要各轴长度是块大小的整数倍),可以这样:
block_size = 3 # 生成新形状:每个轴拆分为 (块数, 块大小) new_shape = [] for dim in the_array.shape: new_shape.extend([dim//block_size, block_size]) new_shape = tuple(new_shape) # 对所有块大小对应的轴(奇数位索引)取均值 mean_axes = tuple(range(1, len(new_shape), 2)) the_array_small = the_array.reshape(new_shape).mean(axis=mean_axes)
修复原apply_over_axes的写法(不推荐)
如果一定要用np.apply_over_axes,需要修复函数的返回值,并且调整均值计算的轴参数:
def mean_over(arr, axis): # reshape后数组形状为(-1, 3),对axis=1取均值才能得到压缩后的结果 return np.average(arr.reshape(-1, 3), axis=1) the_array_small = np.apply_over_axes(mean_over, the_array, [0,1,2])
不过这种方法需要多次遍历数组,效率远低于前面的reshape+mean方案,所以更推荐前者。
内容的提问来源于stack exchange,提问作者Lee Drake
相关产品推荐
相关产品推荐

