如何基于Pandas DataFrame使用Seaborn绘制指定多变量组合图表?
问题描述
需求说明
我需要基于给定的Pandas DataFrame,用Python的Seaborn/Matplotlib绘制指定的多变量组合图表。目标图表已在Excel中制作完成,具体效果为:X轴是SEGM的9到0分类值,左侧Y轴对应YES的数量(柱状图),每个柱子上方标注YES数值和YES%;右侧Y轴对应TOTCUM%(折线图带数据点),每个点标注累计百分比。但我自己写的代码无法实现这个效果,求解决方案。
可重现的DataFrame代码
import pandas as pd dx = {'SEGM':[9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 'YES':[4812, 2697, 2677, 1811, 1570, 1010, 418, 210, 115, 166], 'NO':[590, 1368, 2611, 2968, 3942, 3596, 2141, 1668, 1528, 11055], 'TOT':[5402, 4065, 5288, 4779, 5512, 4606, 2559, 1878, 1643, 11221], 'YES%':[89.08, 66.35, 50.62, 37.89, 28.48, 21.93, 16.33, 11.18, 7.0, 1.48], 'TOTCUM%':[11.51, 20.16, 31.43, 41.6, 53.34, 63.15, 68.6, 72.6, 76.1, 100.0]} dx = pd.DataFrame(dx)
尝试的代码(未成功)
import seaborn as sns import matplotlib.pyplot as plt g=sns.barplot(dx.SEGM, dx['YES'], alpha=0.8) sns.set_style("whitegrid", {'axes.grid' : False}) plt.title(f'{cat_col} with {vol_inperc}%', fontsize = 16,color='blue') plt.ylabel('Volume', fontsize=12) plt.xlabel(f'{cat_col}', fontsize=12) plt.xticks(rotation=90) for p in g.patches: height = p.get_height() g.text(p.get_x()+p.get_width()/2., height + 3, '{} {:1.2f}%'.format(round(height),height/len(df)*100), ha="center", fontsize=10, color='blue') gt = g.twinx()
解决方案代码
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 初始化数据 dx = {'SEGM':[9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 'YES':[4812, 2697, 2677, 1811, 1570, 1010, 418, 210, 115, 166], 'NO':[590, 1368, 2611, 2968, 3942, 3596, 2141, 1668, 1528, 11055], 'TOT':[5402, 4065, 5288, 4779, 5512, 4606, 2559, 1878, 1643, 11221], 'YES%':[89.08, 66.35, 50.62, 37.89, 28.48, 21.93, 16.33, 11.18, 7.0, 1.48], 'TOTCUM%':[11.51, 20.16, 31.43, 41.6, 53.34, 63.15, 68.6, 72.6, 76.1, 100.0]} dx = pd.DataFrame(dx) # 设置无网格的绘图风格 sns.set_style("white", {'axes.grid': False}) fig, ax1 = plt.subplots(figsize=(10,6)) # 绘制左侧柱状图:YES数量 bar_plot = sns.barplot(x='SEGM', y='YES', data=dx, ax=ax1, color='#1f77b4', alpha=0.8) ax1.set_xlabel('SEGM', fontsize=12) ax1.set_ylabel('YES Volume', fontsize=12, color='#1f77b4') ax1.tick_params(axis='y', labelcolor='#1f77b4') # 添加柱状图标注:YES数值 + YES% for idx, p in enumerate(bar_plot.patches): height = p.get_height() yes_pct = dx.iloc[idx]['YES%'] bar_plot.text(p.get_x() + p.get_width()/2., height + 50, f'{int(height)}\n{yes_pct:.2f}%', ha='center', fontsize=10, color='#1f77b4') # 创建右侧Y轴,绘制累计百分比折线图 ax2 = ax1.twinx() line_plot = sns.lineplot(x='SEGM', y='TOTCUM%', data=dx, ax=ax2, marker='o', color='#ff7f0e', linewidth=2) ax2.set_ylabel('Cumulative Total %', fontsize=12, color='#ff7f0e') ax2.tick_params(axis='y', labelcolor='#ff7f0e') ax2.set_ylim(0, 105) # 确保100%的点完整显示 # 添加折线图数据标注 for x, y in zip(dx['SEGM'], dx['TOTCUM%']): ax2.text(x, y + 1, f'{y:.2f}%', ha='center', fontsize=10, color='#ff7f0e') # 设置标题 plt.title('SEGM with YES Volume & Cumulative Total %', fontsize=16, color='blue') # 调整布局避免标签截断 plt.tight_layout() plt.show()
关键修正点
- 补全双轴逻辑:给右侧轴添加了折线图及数据标注
- 修复原代码中未定义的变量(
cat_col、vol_inperc、df) - 调整标注位置,避免数值重叠
- 匹配预期图表的颜色风格,优化视觉效果
- 设置合理Y轴范围,确保所有数据点完整展示
内容的提问来源于stack exchange,提问作者Nabi Shaikh
相关产品推荐
相关产品推荐

