如何为Seaborn双轴图中的折线图添加数据标签
问题:双轴图表中折线图的数据标签无法显示
我用Matplotlib/Seaborn绘制带折线图的双轴图表,尝试给折线图添加数据标签,但始终显示不出来。相关代码、数据和当前图表效果如下:
代码
# Pandas 用于数据管理 import pandas as pd # Matplotlib 用于自定义设置 from matplotlib import pyplot as plt %matplotlib inline # Seaborn 用于绘图和样式设置 import seaborn as sns # 示例数据 data = {'Performance Score': ['PIP', 'To Improve', 'Meet', 'Exceed'], 'Employees by performance score': [2, 17, 201, 30], 'Average Satisfaction': [1.5, 3.6, 3.9, 4.1]} df = pd.DataFrame(data) # 设置图表主题 sns.set_theme(style='dark', rc={'axes.facecolor':'White', 'figure.facecolor':'White'}) fig, ax1 = plt.subplots(figsize=(12,6)) # 绘制双轴图表 # 左Y轴为折线图 sns.lineplot(data = df, y='Average Satisfaction', x='Performance Score', marker='o', sort = False, ax=ax1, color='#97b0df', label='Average Satisfaction') ax2 = ax1.twinx() # 右Y轴为柱状图 sns.barplot(data = df, x = 'Performance Score', y = 'Employees by performance score', alpha=0.8, ax=ax2, color='#2c5494', label='Employees by Performance Score') # 显示柱状图数据标签 for i in ax2.containers: ax2.bar_label(i,)
数据集 df
Performance Score Employees by performance score Average Satisfaction 0 PIP 2 1.5 1 To Improve 17 3.6 2 Meet 201 3.9 3 Exceed 30 4.1
当前图表效果

解决方案
Seaborn的lineplot没有像barplot那样的containers属性可直接遍历添加标签,需要手动获取折线的坐标点,逐个添加文本标签。
修改后的完整代码如下:
# Pandas 用于数据管理 import pandas as pd # Matplotlib 用于自定义设置 from matplotlib import pyplot as plt %matplotlib inline # Seaborn 用于绘图和样式设置 import seaborn as sns # 示例数据 data = {'Performance Score': ['PIP', 'To Improve', 'Meet', 'Exceed'], 'Employees by performance score': [2, 17, 201, 30], 'Average Satisfaction': [1.5, 3.6, 3.9, 4.1]} df = pd.DataFrame(data) # 设置图表主题 sns.set_theme(style='dark', rc={'axes.facecolor':'White', 'figure.facecolor':'White'}) fig, ax1 = plt.subplots(figsize=(12,6)) # 绘制左Y轴折线图,并捕获返回的折线对象 line_plot = sns.lineplot(data = df, y='Average Satisfaction', x='Performance Score', marker='o', sort = False, ax=ax1, color='#97b0df', label='Average Satisfaction') ax2 = ax1.twinx() # 绘制右Y轴柱状图 sns.barplot(data = df, x = 'Performance Score', y = 'Employees by performance score', alpha=0.8, ax=ax2, color='#2c5494', label='Employees by Performance Score') # 显示柱状图数据标签 for i in ax2.containers: ax2.bar_label(i,) # 为折线图添加数据标签 # 从折线对象获取所有数据点的坐标 x_data = line_plot.lines[0].get_xdata() y_data = line_plot.lines[0].get_ydata() # 遍历每个数据点添加格式化标签 for x, y in zip(x_data, y_data): ax1.text(x, y, f'{y:.1f}', ha='center', va='bottom', fontsize=10, color='#97b0df') # 合并两个轴的图例,避免重叠 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') plt.show()
关键说明:
- 捕获
lineplot返回的对象,通过lines[0].get_xdata()和get_ydata()获取折线的所有数据点坐标 - 使用
ax1.text()在每个坐标点添加格式化数值标签,通过ha(水平对齐)和va(垂直对齐)调整位置,避免与折线标记重叠 - 合并双轴的图例,让图表布局更清晰
内容的提问来源于stack exchange,提问作者Tricia Ang
相关产品推荐
相关产品推荐

