如何对不同长度的x、y序列求均值以绘制统一图表?
解决不同长度序列的均值绘图问题
因为不同运行生成的x序列长度、采样点都不统一,直接按位置求均值没有意义。核心思路是先统一x轴,再把所有y值插值到这个统一轴上,最后求均值,具体步骤和代码如下:
实现方案
1. 确定统一的目标x轴(适配对数尺度)
先找出所有x数据的全局范围,然后用对数间隔生成一组均匀的目标x点——这比线性间隔更贴合你的对数尺度需求。
2. 插值对齐所有y序列
对每一次运行的y值,根据其对应的x值,插值到目标x轴上,确保所有y序列长度一致。
3. 计算均值并绘图
把所有插值后的y序列按位置求均值,得到最终的平均曲线,再结合目标x轴绘图。
完整代码示例
import numpy as np import matplotlib.pyplot as plt def algorithm(): """生成等长但每次长度不同的x、y序列,适配对数尺度调整x为正""" length = np.random.randint(low=18, high=22) x_values = np.abs(np.random.randn(length)) * 10 # 确保x为正,适配对数尺度 y_values = 2*x_values + 1 return x_values, y_values n_runs = 10 results = [algorithm() for _ in range(n_runs)] list_x_values = [res[0] for res in results] list_y_values = [res[1] for res in results] # 步骤1:生成统一的对数尺度目标x轴 all_x = np.concatenate(list_x_values) x_min, x_max = all_x.min(), all_x.max() # 生成50个对数间隔的点,数量可按需调整 target_x = np.logspace(np.log10(x_min), np.log10(x_max), num=50) # 步骤2:对每组y进行插值对齐 interpolated_ys = [] for x, y in zip(list_x_values, list_y_values): # 插值要求x单调,所以先对当前运行的x、y按x排序 sorted_idx = np.argsort(x) sorted_x, sorted_y = x[sorted_idx], y[sorted_idx] # 线性插值到目标x,也可替换为scipy的三次样条插值追求平滑 interpolated_y = np.interp(target_x, sorted_x, sorted_y) interpolated_ys.append(interpolated_y) # 步骤3:计算平均y序列 mean_y = np.array(interpolated_ys).mean(axis=0) # 绘图展示 plt.figure(figsize=(10,6)) # 绘制所有单次运行的散点(可选) for x, y in zip(list_x_values, list_y_values): plt.scatter(x, y, alpha=0.3, label='单次运行') # 绘制平均曲线 plt.plot(target_x, mean_y, color='red', linewidth=2, label='平均曲线') plt.xscale('log') # 开启对数x轴 plt.xlabel('X(对数尺度)') plt.ylabel('Y') plt.legend() plt.show()
关键细节说明
- 对数尺度适配:用
np.logspace生成目标x,确保轴上的点在对数尺度下均匀分布;同时必须保证x值为正,对数尺度不支持非正数,实际使用时根据你的真实数据调整x的处理逻辑。 - x排序:插值函数(如
np.interp)要求输入的x是单调递增的,所以每次插值前必须对当前运行的x、y按x排序。 - 插值方法选择:
np.interp是线性插值,简单高效,适合多数场景;- 如果需要更平滑的曲线,可以用
scipy.interpolate.interp1d并设置kind='cubic'(三次样条插值),需要先安装scipy库。
- 目标x点数:
num=50可根据绘图精度调整,点数越多曲线越平滑,但计算量也会增加。
内容的提问来源于stack exchange,提问作者Physics_Student
相关产品推荐
相关产品推荐

