Seaborn使用twinx同图绘制barplot与lineplot失效如何解决
问题根源
你遇到的所有异常都来源于核心问题:seaborn.lineplot默认将日期类型的x轴识别为连续数值,按实际时间间隔分配坐标位置;而seaborn.barplot属于分类图表,会将每个日期当做独立分类,x坐标固定为0、1、2…的整数索引,两者坐标完全错位,直接导致lineplot被渲染到了可见区域外。其余的网格重复、标签混乱、y轴格式不对都属于双轴配置遗漏问题。
修复后完整代码
import seaborn as sns import matplotlib.pyplot as plt def plot1(trades_df): # 处理数据集重复的close_date列 trades_df = trades_df.loc[:, ~trades_df.columns.duplicated()].reset_index(drop=True) n = len(trades_df) x_pos = list(range(n)) # 设置画布尺寸 fig, ax1 = plt.subplots(figsize=(12, 6)) # 绘制左侧y轴柱状图(交易笔数) sns.set_color_codes("pastel") sns.barplot( x=x_pos, y='trades', data=trades_df, label='交易笔数', color='b', alpha=0.6, ax=ax1 ) ax1.set_xlabel('日期', fontsize=12) ax1.set_ylabel('交易笔数', fontsize=12) # 关闭第一个轴的网格避免重复 ax1.grid(False) # 限制左侧y轴刻度为整数 ax1.yaxis.set_major_locator(plt.MaxNLocator(integer=True)) # 生成双轴,绘制右侧y轴折线图(平仓利润) ax2 = ax1.twinx() sns.lineplot( x=x_pos, y='close_profit_abs', data=trades_df, marker='o', label='平仓利润', color='r', linewidth=2, ax=ax2 ) ax2.set_ylabel('平仓利润(绝对值)', fontsize=12) # 仅保留右侧轴的y轴网格,提升可读性 ax2.grid(True, axis='y', linestyle='--', alpha=0.7) # 替换x轴刻度为实际日期 ax1.set_xticks(x_pos) ax1.set_xticklabels(trades_df['close_date'], rotation=90) # 合并双轴图例合并展示 h1, l1 = ax1.get_legend_handles_labels() h2, l2 = ax2.get_legend_handles_labels() ax2.legend(h1 + h2, l1 + l2, loc='upper left') sns.despine(left=True, bottom=True) fig.tight_layout() plt.show() return fig
修改说明
- 统一x轴坐标:两个图表均使用0到n-1的整数索引作为x坐标,保证位置完全对齐,最后再将刻度替换为实际日期,解决x轴混乱、折线不显示的问题。
- 网格配置:关闭第一个轴的网格,仅保留右侧轴的y轴网格,解决网格重复的问题。
- y轴配置:分别给两个轴设置独立的y轴标签,同时用
MaxNLocator限制交易笔数轴的刻度为整数,解决y轴显示浮点的问题。 - 图例合并:将两个轴的图例合并展示,避免图例重叠遮挡图表内容。
- 额外调整了柱状图透明度、折线宽度等样式参数,和你预期的图表效果匹配。
内容的提问来源于stack exchange,提问作者Albert Vonpupp
相关产品推荐
相关产品推荐

