如何为hvplot的字符串日期索引设置X轴刻度及解决datetime转换问题
问题描述
我有一个名为region_cumulative_df_sel的DataFrame,数据结构如下:
| Month-Day | regions | RAIN_PERCENTILE_25 | RAIN_PERCENTILE_50 | RAIN_PERCENTILE_75 | RAIN_MEAN | RAIN_MEDIAN |
|---|---|---|---|---|---|---|
| 07-01 | 1 | 0.0611691028 | 0.2811064720 | 1.9487996101 | 1.4330813885 | 0.2873695195 |
| 07-02 | 1 | 0.0945720226 | 0.8130480051 | 4.5959815979 | 2.9420840740 | 1.0614821911 |
| ... | ... | ... | ... | ... | ... | ... |
| 06-30 | 1 | 386.7952270508 | 450.6524658203 | 514.0201416016 | 471.2863159180 | 451.2484741211 |
其中Month-Day是字符串类型索引,代表一年中的日期(从07-01到06-30),非datetime类型。
遇到两个问题:
- 使用
region_cumulative_df_sel.hvplot(width=900)绘制的交互式图表X轴标签过于密集,需要设置仅显示每月1号(如"07-01"、"08-01"…"06-01")。 - 尝试将
Month-Day转为datetime类型后用pandas plot绘图,出现X轴刻度与数据不对齐、交互弹窗显示"1900"年份的问题,需要调整刻度对齐并移除年份显示。
解决方案
一、hvplot设置X轴仅显示每月1号刻度
方案1:基于原字符串索引直接设置
利用字符串索引筛选每月1号的日期,手动指定X轴刻度:
# 从索引中筛选所有以"-01"结尾的日期(即每月1号) tick_positions = [date for date in region_cumulative_df_sel.index if date.endswith('-01')] # 绘制图表并配置X轴 region_cumulative_df_sel.hvplot( width=900, xaxis={ 'ticks': tick_positions, # 指定刻度位置 'formatter': '%m-%d', # 刻度显示格式 'rotation': 90 # 可选:旋转刻度标签避免重叠 } )
方案2:转为datetime类型后设置(更灵活)
将字符串索引转为datetime时指定一个虚拟年份(如2023),避免默认1900年的问题,再设置每月1号的刻度:
import pandas as pd # 重置索引并转换日期格式,指定年份为2023 df = region_cumulative_df_sel.reset_index() df['Month-Day'] = pd.to_datetime('2023-' + df['Month-Day']) # 生成每月1号的datetime序列作为刻度 tick_dates = pd.date_range(start='2023-07-01', end='2024-06-01', freq='MS') # 绘制图表 df.hvplot( x='Month-Day', width=900, xaxis={ 'ticks': tick_dates, 'formatter': '%m-%d', 'rotation': 90 } )
二、解决pandas plot的刻度对齐与年份显示问题
问题根源:转换%m-%d时默认填充1900年,且pandas自动生成的刻度与数据点不对齐。解决步骤如下:
import pandas as pd from bokeh.models.formatters import DatetimeTickFormatter from bokeh.models import HoverTool import matplotlib.pyplot as plt # 1. 转换日期时指定年份(避免1900) df = region_cumulative_df_sel.reset_index() df['Month-Day'] = pd.to_datetime('2023-' + df['Month-Day'], format='%Y-%m-%d') # 2. 生成每月1号的刻度日期 tick_dates = pd.date_range(start='2023-07-01', end='2024-06-01', freq='MS') # 3. 绘制基础图表 p = df.plot( x='Month-Day', y=['RAIN_PERCENTILE_25','RAIN_PERCENTILE_50','RAIN_PERCENTILE_75','RAIN_MEAN','RAIN_MEDIAN'], width=900, ylabel="Rainfall (mm)", rot=90, title="Cumulative Rainfall" ) # 4. 设置X轴刻度与格式,确保对齐 p.xaxis.ticker = tick_dates p.xaxis.formatter = DatetimeTickFormatter(days=["%m-%d"], months=["%m-%d"]) # 5. 自定义hover弹窗,移除年份显示 hover = p.select_one(HoverTool) hover.tooltips = [ ("Date", "@x{%m-%d}"), ("Rainfall", "@y{0.2f} mm") ] hover.formatters = {'@x': 'datetime'} # 显示图表 plt.show()
内容的提问来源于stack exchange,提问作者alextc
相关产品推荐
相关产品推荐

