基于2D区域数组处理3D数组并生成区域时间序列均值统计
问题描述
给定一个3D数组(第一维度为时间索引,后两个维度为空间坐标),以及一个2D区域定义数组(0代表无效区域,包含4个编号为1-4的有效区域)。需要生成每个有效区域随时间变化的均值时间序列,最终得到4条长度为10的序列。
示例输入代码:
import numpy as np # 创建示例3D数组(时间维度10,空间维度6x6) sampl = np.random.uniform(low=0.1, high=10, size=(10,6,6)) # 生成示例区域数组(先展平,后续可重塑为6x6) zn = np.array([ 0,1,1,2,2,0, 1,1,1,2,2,2, 1,1,1,2,2,2, 3,3,3,4,4,4, 3,3,3,4,4,4, 0,0,3,4,0,0, ])
解决方案
以下是两种基于NumPy的实现方式,兼顾可读性和性能:
方法一:掩码遍历实现(直观易理解)
import numpy as np # 初始化示例数据 sampl = np.random.uniform(low=0.1, high=10, size=(10,6,6)) zn = np.array([ 0,1,1,2,2,0, 1,1,1,2,2,2, 1,1,1,2,2,2, 3,3,3,4,4,4, 3,3,3,4,4,4, 0,0,3,4,0,0, ]).reshape(6,6) # 将区域数组重塑为与空间维度匹配的2D结构 # 获取所有有效区域编号 zone_ids = np.unique(zn[zn != 0]) # 初始化结果数组:4个区域 × 10个时间点的均值 zone_time_means = np.zeros((len(zone_ids), sampl.shape[0])) # 遍历每个区域计算时间序列均值 for i, zone_id in enumerate(zone_ids): # 生成当前区域的空间掩码 mask = (zn == zone_id) # 对每个时间步,提取区域内的所有空间点并计算均值 zone_time_means[i] = sampl[:, mask].mean(axis=1) # 输出结果:每一行对应一个区域的时间均值序列 print(zone_time_means)
代码说明
- 先将展平的区域数组
zn重塑为6×6的2D结构,与3D数组的空间维度对齐; - 通过
np.unique(zn[zn !=0])自动识别所有有效区域编号,无需手动指定; - 利用布尔掩码筛选目标区域的空间点,
sampl[:, mask]会将每个时间步的区域点展平为一维数组,再通过mean(axis=1)计算该时间步的均值。
方法二:向量化分组统计(无循环,性能更优)
如果处理大规模数据,可使用np.bincount实现纯向量化的分组计算:
import numpy as np # 初始化示例数据 sampl = np.random.uniform(low=0.1, high=10, size=(10,6,6)) zn = np.array([ 0,1,1,2,2,0, 1,1,1,2,2,2, 1,1,1,2,2,2, 3,3,3,4,4,4, 3,3,3,4,4,4, 0,0,3,4,0,0, ]).reshape(6,6) # 将3D数组展平为(时间步,空间点)的2D结构 sampl_flat = sampl.reshape(sampl.shape[0], -1) # 将区域数组展平为一维 zn_flat = zn.flatten() # 遍历每个时间步,用bincount计算区域总和与点数,再求均值 zone_time_means = [] for time_data in sampl_flat: # 计算每个区域的数值总和 zone_sums = np.bincount(zn_flat, weights=time_data, minlength=5)[1:] # 计算每个区域的有效点数 zone_counts = np.bincount(zn_flat, minlength=5)[1:] # 计算均值并添加到结果列表 zone_time_means.append(zone_sums / zone_counts) # 转置得到(区域数,时间步)的最终结果 zone_time_means = np.array(zone_time_means).T
内容的提问来源于stack exchange,提问作者user2256085
相关产品推荐
相关产品推荐

