You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

30个CSV文件绘制直方图、高斯拟合求峰均值标准差及代码问题咨询

多峰高斯拟合与直方图绘制完整解决方案

报错修复

你遇到的np.arange相关报错是因为Python内置min()/max()无法直接处理多维numpy数组,np.all()为逻辑判断函数,仅返回单个布尔值,完全不适合用来取极值。正确写法如下:

import numpy as np
# numpy的全局极值函数会自动展平数组,读取所有元素的最大/最小值
Xs = np.arange(np.min(voltages), np.max(voltages), 0.05)

直方图逻辑校验

第三个峰幅度过低可按以下两点排查:

  • 调整np.histogram的bin参数:bin数量过少会合并相邻峰,过多会拆分低幅峰为离散碎点,优先用bins='auto'让numpy自动计算最优bin数
  • 调整savgol_filter平滑参数:窗口长度必须为奇数,且远小于峰的宽度,窗口过大会直接抹平低幅峰,常规三峰场景设置窗口长度为5、多项式阶数为2即可:
from scipy import signal
counts, bins = np.histogram(voltages, bins='auto')
bin_centers = (bins[:-1] + bins[1:]) / 2
smooth_counts = signal.savgol_filter(counts, window_length=5, polyorder=2)

绘图标签不显示修复

设置label后未显示的核心原因是未调用图例渲染函数,完整绘图流程参考:

import matplotlib.pyplot as plt
plt.hist(voltages.flatten(), bins='auto', label='原始直方图')
plt.plot(bin_centers, smooth_counts, c='orange', label='平滑后直方图')
plt.xlabel('电压(V)')
plt.ylabel('频数')
# 必须添加该行才能渲染所有label
plt.legend()
plt.show()

三峰高斯拟合实现

直接拼接单高斯函数即可得到多峰拟合函数,用scipy的curve_fit工具完成拟合,参考代码:

from scipy.optimize import curve_fit

# 单高斯函数:A为振幅,mu为均值,sigma为标准差
def gauss(x, A, mu, sigma):
    return A * np.exp(-(x - mu)**2 / (2 * sigma**2))

# 三峰高斯函数为三个单高斯的叠加
def tri_gauss(x, A1, mu1, sigma1, A2, mu2, sigma2, A3, mu3, sigma3):
    return gauss(x, A1, mu1, sigma1) + gauss(x, A2, mu2, sigma2) + gauss(x, A3, mu3, sigma3)

# 设置拟合初值,根据直方图的峰位、峰高、峰宽手动调整,初值越接近真实值拟合成功率越高
# 初值顺序:A1, mu1, sigma1, A2, mu2, sigma2, A3, mu3, sigma3
p0 = [100, 1, 0.2, 80, 2, 0.2, 30, 3, 0.2]
# 执行拟合
popt, pcov = curve_fit(tri_gauss, bin_centers, smooth_counts, p0=p0)

拟合输出的popt数组已包含所有目标参数:

  • 三个峰的均值依次为popt[1]、popt[4]、popt[7]
  • 三个峰的标准差依次为popt[2]、popt[5]、popt[8]

峰参数获取方案

优先通过高斯拟合结果获取峰均值和标准差,精度远高于直接定位局部最大值,可有效规避噪声干扰。如果需要直接定位峰位,可使用scipy的峰值检测工具:

from scipy.signal import find_peaks
# height为最小峰高阈值,distance为相邻峰最小间隔,根据实际数据调整
peaks, _ = find_peaks(smooth_counts, height=20, distance=10)
# peaks对应的bin中心坐标即为峰位
peak_centers = bin_centers[peaks]

多峰单独标准差计算

若通过高斯拟合已得到sigma参数可直接使用,无需额外计算。如果需要用原始数据单独计算每个峰的标准差,可按峰位切分对应区间的数据后再调用np.std:

# 以第一个峰在1附近为例,切分0.8~1.2区间内的原始电压数据
peak1_data = voltages[(voltages > 0.8) & (voltages < 1.2)]
peak1_std = np.std(peak1_data)

内容的提问来源于stack exchange,提问作者Physics World

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 10:09:05