Python中Bokeh绘图自定义分类刻度标签:解决标签拥挤问题
我来帮你搞定这个Bokeh轴标签的问题!你不想用x_axis_type="datetime"又嫌CategoricalAxis的366个刻度太拥挤,其实用自定义固定刻度+标签的方式就能完美解决,既清爽又符合你要显示“1 January”这类无年份标签的需求。
核心思路
放弃CategoricalAxis,改用LinearAxis配合FixedTicker和FuncTickFormatter:
- 用
FixedTicker手动指定你想显示的刻度位置(比如每月第一天对应的x坐标) - 用
FuncTickFormatter把这些位置映射成“1 January”格式的标签 - 这样只会显示你指定的12个(或13个,闰年)刻度,完全不会拥挤
具体代码实现
假设你的数据是包含日期和数值的DataFrame,我给你写个可直接参考的示例:
from bokeh.plotting import figure, show from bokeh.models import FixedTicker, FuncTickFormatter, LinearAxis import pandas as pd import numpy as np # 模拟1950-2015的每日数据,替换成你自己的数据集即可 dates = pd.date_range(start='1950-01-01', end='2015-12-31', freq='D') df = pd.DataFrame({ 'date': dates, 'value': np.random.randn(len(dates)) # 替换成你的实际数值列 }) # 生成"1 January"格式的标签,并标记每月第一天 df['day_month_label'] = df['date'].dt.strftime('%d %B') df['is_first_day'] = df['date'].dt.is_month_start # 提取每月第一天的x位置(这里假设x用数据的索引,你也可以换成一年中的天数:df['date'].dt.dayofyear) first_day_x_positions = df[df['is_first_day']].index.tolist() # 对应的标签列表 first_day_labels = df[df['is_first_day']]['day_month_label'].tolist() # 创建基础绘图,不用datetime轴 p = figure( plot_width=900, plot_height=450, x_axis_label='Date', y_axis_label='Value', tools='pan,box_zoom,reset' ) p.line(df.index, df['value']) # x用索引,替换成你的x列 # 隐藏默认的x轴,避免重复 p.xaxis.visible = False # 添加自定义x轴 custom_x_axis = LinearAxis( ticker=FixedTicker(ticks=first_day_x_positions), formatter=FuncTickFormatter(code=f""" const labels = {first_day_labels}; return labels[ticks.indexOf(tick)]; """) ) p.add_layout(custom_x_axis, 'below') show(p)
额外调整建议
- 如果你的x轴是按一年中的天数(1-366)来绘制(比如把所有年份的同一天叠在一起),只需要把
df.index换成df['date'].dt.dayofyear,同时first_day_x_positions换成每月第一天的天数(比如1,32,61...)即可。 - 要是觉得12个刻度还是有点密,可以改成只显示季度第一天的标签,只需要把
is_month_start换成df['date'].dt.quarter != df['date'].shift(1).dt.quarter来筛选季度起始日就行。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

