Pandas日期索引下堆叠柱状图叠加双轴折线图异常排查
问题原因与解决方案
问题根源
当你用df.plot.bar(stacked=True)绘制带日期索引的堆叠柱状图时,Pandas会自动将日期索引转换为分类型X轴——每个日期对应一个分类标签,柱子的实际位置是从0开始的连续整数(0,1,2...19)。但后续调用series.plot(ax=ax, secondary_y=True)时,Pandas会把Series的日期索引当作连续时间轴处理,直接用日期的数值(时间戳)作为X坐标,这就导致折线图的X轴范围和柱状图的分类轴完全错位,看起来像是折线图覆盖了柱状图。而用整数索引时,两者的X轴都是基于整数位置的轴,所以能正常匹配。
解决方案
这里提供三种可行的修复方法:
方法1:手动对齐折线图的X轴位置
利用柱状图的X轴位置(0到n-1)来绘制折线图,同时保留日期作为X轴标签:
import pandas as pd import numpy as np idx = pd.date_range(start='2000-01-01', periods=20) df = pd.DataFrame(np.random.rand(20,3), index=idx) ax = df.plot.bar(stacked=True) # 获取柱状图的X轴位置(0到19) x_pos = range(len(df)) series = pd.Series(np.random.rand(20), index=idx) # 用Matplotlib直接绘制折线图,指定X位置为x_pos ax2 = ax.twinx() ax2.plot(x_pos, series.values, color='red', marker='o') # 设置次轴的Y轴标签(可选) ax2.set_ylabel('Series Value')
方法2:将日期索引转换为字符串,统一用分类轴
把日期转成字符串后,柱状图和折线图都会用分类轴,自然匹配:
import pandas as pd import numpy as np idx = pd.date_range(start='2000-01-01', periods=20) # 把日期索引转为字符串 df = pd.DataFrame(np.random.rand(20,3), index=idx.strftime('%Y-%m-%d')) ax = df.plot.bar(stacked=True) series = pd.Series(np.random.rand(20), index=idx.strftime('%Y-%m-%d')) series.plot(ax=ax, secondary_y=True, color='red', marker='o')
方法3:用Matplotlib原生API完全控制(更灵活)
直接用Matplotlib创建轴对象,分别绘制柱状图和折线图,精准控制X轴:
import pandas as pd import numpy as np import matplotlib.pyplot as plt idx = pd.date_range(start='2000-01-01', periods=20) df = pd.DataFrame(np.random.rand(20,3), index=idx) series = pd.Series(np.random.rand(20), index=idx) fig, ax1 = plt.subplots() # 绘制堆叠柱状图 ax1.bar(df.index, df[0], label='Col0') ax1.bar(df.index, df[1], bottom=df[0], label='Col1') ax1.bar(df.index, df[2], bottom=df[0]+df[1], label='Col2') ax1.set_xticks(idx) ax1.set_xticklabels(idx.strftime('%Y-%m-%d'), rotation=45) ax1.set_ylabel('Stacked Bar Value') ax1.legend() # 绘制次轴折线图 ax2 = ax1.twinx() ax2.plot(idx, series, color='red', marker='o', label='Series') ax2.set_ylabel('Series Value') ax2.legend(loc='upper right') plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

