在带MultiIndex的Pandas折线图中添加竖线并控制X轴标签
MultiIndex DataFrame 绘图问题解决方案
针对给定的MultiIndex(date+rank)结构的DataFrame,以下是两个绘图需求的具体解决方案:
问题1:在MultiIndex X轴指定位置添加竖线
问题根源
直接使用(date, rank)格式的MultiIndex元组作为竖线位置时,matplotlib无法识别该格式,因此抛出ConversionError。正确做法是将MultiIndex位置转换为DataFrame对应的行索引序号(即数据在表格中的行号)。
实现代码
import pandas as pd import matplotlib.pyplot as plt # 初始化数据 dx = pd.DataFrame({ "date": [ pd.to_datetime('2025-02-24'), pd.to_datetime('2025-02-24'), pd.to_datetime('2025-02-24'), pd.to_datetime('2025-02-24'), pd.to_datetime('2025-02-25'), pd.to_datetime('2025-02-25'), pd.to_datetime('2025-02-25'), pd.to_datetime('2025-02-26'), pd.to_datetime('2025-02-26'), pd.to_datetime('2025-02-26'), pd.to_datetime('2025-02-26'), pd.to_datetime('2025-02-26') ], "rank": [0.0,1.0,2.0,100.0,0.0,1.0,100.0,0.0,1.0,2.0,3.0,100.0], "value": [2.3, 2.5, 2.4, 2.36, 2.165, 2.54, 2.34, 2.12, 2.32, 2.43, 2.4, 2.3] }) dx.set_index(["date", "rank"], inplace=True) # 创建绘图对象 fig, ax = plt.subplots() dx['value'].plot(ax=ax) # 筛选rank=1和rank=100的MultiIndex位置 rank1_indices = dx.index[dx.index.get_level_values('rank') == 1.0] rank100_indices = dx.index[dx.index.get_level_values('rank') == 100.0] # 绘制rank=1的红色虚线竖线 for idx_tuple in rank1_indices: row_pos = dx.index.get_loc(idx_tuple) ax.axvline(x=row_pos, color='red', linestyle='--', alpha=0.7) # 绘制rank=100的蓝色点线竖线 for idx_tuple in rank100_indices: row_pos = dx.index.get_loc(idx_tuple) ax.axvline(x=row_pos, color='blue', linestyle=':', alpha=0.7) plt.tight_layout() plt.show()
关键说明
dx.index.get_loc(idx_tuple):将MultiIndex元组转换为对应的行号,matplotlib可直接用该数值作为x轴坐标。- 通过
alpha参数调整竖线透明度,避免遮挡折线数据。
问题2:仅显示rank=0的X轴标签
实现思路
遍历X轴所有刻度对应的MultiIndex项,仅保留rank=0的标签文本,其余标签设为空字符串,从而实现只显示目标标签的效果。
实现代码
# 接上述绘图代码,在绘制竖线后添加以下逻辑 # 获取当前X轴的刻度与标签 ticks = ax.get_xticks() new_labels = [] for tick_pos in ticks: # 获取刻度对应的MultiIndex元组 current_idx = dx.index[int(tick_pos)] # 仅保留rank=0的日期标签,其余设为空 if current_idx[1] == 0.0: new_labels.append(current_idx[0].strftime('%Y-%m-%d')) else: new_labels.append("") # 更新X轴标签 ax.set_xticklabels(new_labels) # 可选:旋转标签避免重叠 plt.xticks(rotation=45) plt.tight_layout() plt.show()
关键说明
current_idx[0].strftime('%Y-%m-%d'):将日期格式化为易读的字符串,可根据需求调整格式。- 无需依赖旋转标签的“曲线救国”方式,直接通过控制标签内容实现需求。
内容的提问来源于stack exchange,提问作者dayum
相关产品推荐
相关产品推荐

