Seaborn绘图使用twinx()后x轴显示错位异常问题求助
问题原因与修复方案
核心错误原因
seaborn.barplot属于分类图类型,无论传入的x轴字段dt_mvtc是字符串还是日期格式,都会自动将所有x值按出现顺序映射到0,1,2...n-1的整数位置,x轴本质是分类索引轴。seaborn.lineplot属于连续数值图类型,如果dt_mvtc是日期格式,会直接用日期对应的时间戳数值作为x坐标,和barplot的分类索引完全不匹配,因此出现标签错位。- 你观察到注释掉
ax2 = ax.twinx()后x轴显示正常,是因为单轴绘图时不会触发两个不同坐标体系的冲突,问题根源并非twinx本身,而是两类图表的x坐标映射规则不统一。 - 额外的代码不规范问题:调用
plt.xticks、plt.xlabel这类全局pyplot方法时,默认作用于最后创建的轴也就是ax2,进一步加剧了x轴配置的混乱。
修复方案
提供两种常用适配方案,可根据需求选择:
方案1:强制lineplot使用和barplot一致的分类索引
适合需要保留seaborn barplot默认样式的场景,修改后代码如下:
from matplotlib.ticker import ScalarFormatter import seaborn as sns import matplotlib.pyplot as plt import pandas as pd fig, ax = plt.subplots(figsize=(20, 10)) ax2 = ax.twinx() # 预筛选绘图数据集,避免多次query结果不一致 plot_df = df_grafico_merge.query('t0_def_qtt==1').reset_index(drop=True) # 绘制barplot sns.barplot(x="dt_mvtc", y="qtde_t0", data=plot_df, color='blue', ax=ax) # 获取barplot的分类位置和标签 x_ticks = ax.get_xticks() x_labels = [label.get_text() for label in ax.get_xticklabels()] # 绘制lineplot时直接用barplot的位置作为x值,保证坐标完全对齐 sns.lineplot(x=x_ticks, y='qtde_t12', hue='t12_def_qtt', style='t12_def_qtt', data=plot_df, markers=True, color='orange', ax=ax2) # 所有轴配置明确指定对应轴,避免全局调用混乱 ax.set_xlabel("Data") ax.set_ylabel("Quantidade (柱状图)") ax2.set_ylabel("Quantidade (折线图)") ax.set_title('Qtde de registros por data e t0=1') # 统一在主轴设置x轴刻度和旋转 ax.set_xticks(x_ticks) ax.set_xticklabels(x_labels, rotation=90, ha='right') formatter = ScalarFormatter() formatter.set_scientific(True) ax.yaxis.set_major_formatter(formatter) plt.tight_layout() plt.show()
方案2:使用原生matplotlib bar替代seaborn barplot
适合需要保留x轴日期连续属性的场景,修改后代码如下:
from matplotlib.ticker import ScalarFormatter import seaborn as sns import matplotlib.pyplot as plt import pandas as pd fig, ax = plt.subplots(figsize=(20, 10)) ax2 = ax.twinx() plot_df = df_grafico_merge.query('t0_def_qtt==1').reset_index(drop=True) # 原生bar支持连续日期作为x坐标,和lineplot坐标体系统一 ax.bar(x=plot_df['dt_mvtc'], height=plot_df['qtde_t0'], color='blue', width=0.7) sns.lineplot(x="dt_mvtc", y='qtde_t12', hue='t12_def_qtt', style='t12_def_qtt', data=plot_df, markers=True, color='orange', ax=ax2) ax.set_xlabel("Data") ax.set_ylabel("Quantidade (柱状图)") ax2.set_ylabel("Quantidade (折线图)") ax.set_title('Qtde de registros por data e t0=1') plt.setp(ax.get_xticklabels(), rotation=90, ha='right') formatter = ScalarFormatter() formatter.set_scientific(True) ax.yaxis.set_major_formatter(formatter) plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Silvio sjsj
相关产品推荐
相关产品推荐

