不同采样点下采样数据均值的绘制方法咨询
非重合采样点的多组数据均值绘制方案
问题背景
需要绘制多组采样数据的均值曲线,但各组对应的采样点x并不重合,且x取值范围限定在0到1之间。给定的示例代码如下:
import matplotlib.pyplot as plt x1 = [0.1, 0.2, 0.4, 0.6, 0.75, 0.9] x2 = [0, 0.14, 0.53, 0.6, 0.81, 0.9, 0.98] y1 = [1, 4, 6, 5, 5, 3] y2 = [3, 4, 7, 9, 7, 4, 2] plt.plot(x1, y1, marker='o') plt.plot(x2, y2, marker='x') plt.grid() plt.xlabel('x') plt.ylabel('y') plt.show()
以下是几种符合Python风格的优雅实现方式,包含插值方案和更优替代方案:
一、插值统一x轴(标准方案)
如果需要严格对齐x轴后计算均值,用numpy.interp或scipy.interp1d实现是最直接且Pythonic的方式。可以封装成通用函数处理多组数据:
实现代码
import numpy as np import matplotlib.pyplot as plt # 定义通用插值函数 def interpolate_and_average(x_list, y_list, num_points=100): # 生成统一的x轴(0到1之间均匀采样) x_uniform = np.linspace(0, 1, num_points) # 对每组数据插值 y_interpolated = [np.interp(x_uniform, x, y) for x, y in zip(x_list, y_list)] # 计算均值 y_mean = np.mean(y_interpolated, axis=0) return x_uniform, y_mean # 准备数据 x_data = [x1, x2] y_data = [y1, y2] # 计算插值后的均值曲线 x_uniform, y_mean = interpolate_and_average(x_data, y_data) # 绘图 plt.plot(x1, y1, marker='o', alpha=0.5, label='Dataset 1') plt.plot(x2, y2, marker='x', alpha=0.5, label='Dataset 2') plt.plot(x_uniform, y_mean, color='red', linewidth=2, label='Mean Curve') plt.grid() plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()
优势
- 逻辑清晰,代码简洁,符合Python的函数式编程风格
- 可以灵活控制采样点数,平衡精度和效率
- 支持扩展到任意多组数据
二、无需统一x轴的替代方案
如果不需要强制对齐x点,而是想要更平滑的均值趋势,可以用核密度估计(KDE)或局部加权回归(LOWESS),这类方法更适合数据分布有规律的场景:
1. 核密度估计(KDE)平滑均值
利用KDE对所有(x,y)点进行加权,生成平滑的均值曲线:
import numpy as np import matplotlib.pyplot as plt from scipy.stats import gaussian_kde # 合并所有数据点 all_x = np.concatenate([x1, x2]) all_y = np.concatenate([y1, y2]) # 生成KDE模型,计算每个x点的加权均值 x_uniform = np.linspace(0, 1, 100) kde = gaussian_kde(np.vstack([all_x, all_y])) # 计算每个x对应的y均值(通过KDE加权) y_mean = [] for x in x_uniform: # 固定x,采样y的条件分布 y_samples = kde.resample(size=1000, seed=42)[1] y_mean.append(np.mean(y_samples)) # 绘图 plt.plot(x1, y1, marker='o', alpha=0.5, label='Dataset 1') plt.plot(x2, y2, marker='x', alpha=0.5, label='Dataset 2') plt.plot(x_uniform, y_mean, color='green', linewidth=2, label='KDE Mean Curve') plt.grid() plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()
2. 局部加权回归(LOWESS)
用LOWESS拟合所有数据点,得到平滑的趋势线,本质是局部区域内的加权均值:
import numpy as np import matplotlib.pyplot as plt from statsmodels.nonparametric.smoothers_lowess import lowess # 合并所有数据点 all_x = np.concatenate([x1, x2]) all_y = np.concatenate([y1, y2]) # 用LOWESS拟合 lowess_result = lowess(all_y, all_x, frac=0.3) # frac控制平滑程度 x_smooth = lowess_result[:, 0] y_smooth = lowess_result[:, 1] # 绘图 plt.plot(x1, y1, marker='o', alpha=0.5, label='Dataset 1') plt.plot(x2, y2, marker='x', alpha=0.5, label='Dataset 2') plt.plot(x_smooth, y_smooth, color='blue', linewidth=2, label='LOWESS Mean Curve') plt.grid() plt.xlabel('x') plt.ylabel('y') plt.legend() plt.show()
优势
- 不需要强制插值,保留原始数据的分布特征
- 生成的曲线更平滑,适合展示整体趋势
- 对数据中的噪声有一定的鲁棒性
方案选择建议
- 如果需要精确对齐x点并计算均值,优先选择插值方案
- 如果更关注整体趋势的平滑展示,且数据分布有规律,建议用KDE或LOWESS
- 多组数据量较大时,插值方案的效率更高;数据量较小时,KDE/LOWESS的效果更自然
内容的提问来源于stack exchange,提问作者Isotope
相关产品推荐
相关产品推荐

