基于核密度估计的折线图小提琴图等效:不确定性颜色编码可视化
解决方案与错误修复
错误原因分析
你遇到的LinAlgError: singular matrix是因为:
stats.gaussian_kde默认将输入的二维数组每一行视为一个多维样本,但你的数据结构是每个x位置对应一行10个一维y样本,直接传入整个二维数组会让KDE错误地处理成50个10维样本,维度逻辑完全错误。- 即使维度正确,当样本量较小(比如n=10)时,若样本分布过于集中,协方差矩阵会出现奇异情况,导致计算失败。
可视化实现思路
要实现类似小提琴图的渐变阴影(颜色深浅对应概率密度),核心是对每个x位置的y样本单独做一维核密度估计,然后将所有x位置的密度值组合成二维矩阵,用pcolormesh或contourf绘制渐变区域。
完整修正代码
import numpy as np import matplotlib.pyplot as plt from scipy import stats # %% 生成随机数据 x = np.linspace(0, 6*np.pi, 50) def sin_normal(n, x): m1 = np.abs(np.random.lognormal(size=n, sigma=1.5)) return np.array([np.sin(x)]*n).T + m1 + 1 # 保证y值为正 y = sin_normal(10, x) y_mean = y.mean(axis=1) # 定义y轴网格(线性坐标) ymin, ymax = y.min(), y.max() y_grid_lin = np.linspace(ymin, ymax, 100) # 定义y轴网格(对数坐标,适配loglog图) y_grid_log = np.logspace(np.log10(ymin), np.log10(ymax), 100) # %% 逐x位置计算核密度估计 # 线性坐标下的密度矩阵 Z_lin = np.zeros((len(y_grid_lin), len(x))) for i in range(len(x)): y_sample = y[i, :] # 指定带宽方法避免奇异矩阵,silverman/scott是常用自动规则,也可手动设factor(如0.5) kde = stats.gaussian_kde(y_sample, bw_method='silverman') Z_lin[:, i] = kde(y_grid_lin) # 对数坐标下的密度矩阵 Z_log = np.zeros((len(y_grid_log), len(x))) for i in range(len(x)): y_sample = y[i, :] kde = stats.gaussian_kde(y_sample, bw_method='silverman') Z_log[:, i] = kde(y_grid_log) # %% 绘制可视化 fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8)) # 线性坐标图 # 绘制密度渐变阴影 pcm = ax1.pcolormesh(x, y_grid_lin, Z_lin, cmap='Blues', alpha=0.6, shading='gouraud') # 叠加均值线 ax1.plot(x, y_mean, 'r-', linewidth=2, label='Mean') # 可选:绘制原始数据 ax1.plot(x, y, '-', markersize=2, alpha=0.3) ax1.set_ylabel('Y (Linear Scale)') ax1.legend() # 对数坐标图 pcm_log = ax2.pcolormesh(x, y_grid_log, Z_log, cmap='Blues', alpha=0.6, shading='gouraud') ax2.loglog(x, y_mean, 'r-', linewidth=2, label='Mean') ax2.loglog(x, y, '-', markersize=2, alpha=0.3) ax2.set_xlabel('X') ax2.set_ylabel('Y (Log Scale)') ax2.legend() # 添加颜色条(可选,展示密度与颜色的对应关系) fig.colorbar(pcm, ax=[ax1, ax2], label='Probability Density') plt.tight_layout() plt.show()
关键细节说明
- 逐行KDE处理:对每个x对应的y样本单独计算一维KDE,确保密度估计的逻辑正确。
- 带宽调整:通过
bw_method指定带宽计算规则(silverman/scott),或手动设置bw_method=0.5这类数值缩小带宽,避免样本量小时出现奇异矩阵。 - 渐变阴影绘制:
pcolormesh的shading='gouraud'参数让颜色过渡更平滑,cmap选择合适的配色(如Blues),alpha调整透明度避免遮挡均值线。 - 对数坐标适配:对数图中使用
np.logspace生成y轴网格,保证密度估计在对数尺度下的合理性。
内容的提问来源于stack exchange,提问作者LibrEars
相关产品推荐
相关产品推荐

