如何在Seaborn子图中获取分布曲线峰值X值并绘制垂直线
解决子图中KDE曲线峰值垂直线与标注问题
要在子图的每条KDE曲线上添加峰值垂直线和X轴标注,核心是针对每个子图的轴对象,提取曲线数据并计算峰值位置,再在对应子图上绘制元素。以下是修改后的可运行代码:
from pylab import * import matplotlib.pyplot as plt import seaborn as sns import numpy as np # 生成示例数据 input1 = np.random.normal(loc=0.2, scale=1.0, size=25) output1 = np.random.normal(loc=0.3, scale=1.0, size=25) input2 = np.random.normal(loc=0.1, scale=1.0, size=25) output2 = np.random.normal(loc=0.15, scale=1.0, size=25) inputs = [input1, input2] outputs = [output1, output2] my_alpha = 0.03 my_linewidth = 0.7 for i in range(len(inputs)): # 创建子图并获取当前轴对象 ax = plt.subplot(1, 2, i+1) # 绘制两条KDE曲线 sns.kdeplot(inputs[i], shade=True, alpha=my_alpha, linewidth=my_linewidth, label='Input Playlist', color='#2cc758', ax=ax) sns.kdeplot(outputs[i], shade=True, alpha=my_alpha, linewidth=my_linewidth, label='Recommandations Made', color='#dbb818', ax=ax) # 遍历当前子图中的每条曲线,处理峰值标注 for line in ax.lines: # 获取曲线的x、y数据 x_data = line.get_xdata() y_data = line.get_ydata() # 找到y最大值对应的索引,得到峰值的x坐标 peak_idx = np.argmax(y_data) peak_x = x_data[peak_idx] peak_y = y_data[peak_idx] # 绘制垂直线:从x轴(y=0)到峰值顶部 ax.vlines(x=peak_x, ymin=0, ymax=peak_y, color=line.get_color(), linestyle='--', linewidth=0.8) # 在X轴上方标注峰值的x值(保留两位小数) ax.text(x=peak_x, y=0, s=f'{peak_x:.2f}', ha='center', va='top', fontsize=8, color=line.get_color()) # 调整图例位置与样式 myLegend = plt.legend(loc='lower left', bbox_to_anchor=(-1.2, 1.05), ncol=2) myLegend.set_title("Tracks Set") plt.setp(myLegend.get_title()) # 调整子图间距,避免元素重叠 plt.tight_layout() plt.show()
关键说明:
- 子图轴对象控制:每个循环中明确获取当前子图的
ax对象,所有绘制操作都基于这个轴,确保元素画在正确的子图上。 - 提取曲线数据:通过
ax.lines获取当前子图内的所有曲线,每条曲线的get_xdata()和get_ydata()能拿到KDE的数值点。 - 峰值计算:用
np.argmax(y_data)找到y值最大的位置,对应就是KDE曲线的峰值点。 - 垂直线与标注:用
ax.vlines绘制垂直线,ax.text在X轴上方标注峰值的x坐标,颜色与对应曲线保持一致,提升可读性。
内容的提问来源于stack exchange,提问作者Anto69
相关产品推荐
相关产品推荐

