You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bokeh/HoloViews热力图中处理时间与分类轴及刻度重叠问题?

解决Bokeh/HoloViews大分类y轴刻度重叠的问题

针对你遇到的3000+分类变量导致y轴刻度完全重叠的问题,结合Bokeh 1.2.0版本和Datashader的要求,这里有几个可靠的解决方案:

方法1:自定义JavaScript回调实现动态刻度(适配Bokeh 1.2.0)

Bokeh的默认分类轴不会自动根据缩放调整刻度数量,但你可以通过CustomJS监听视图的范围变化,动态生成仅包含可见区域内合适数量的刻度标签。

修改你的示例代码,添加y轴的动态刻度回调:

from datetime import datetime
import pandas as pd
import numpy as np
from bokeh.plotting import figure, show
from bokeh.transform import linear_cmap
from bokeh.io import output_notebook
from bokeh.models import CustomJS

output_notebook()

# 构建样本数据(模拟3000个分类)
index = pd.date_range(start='1/1/2019', periods=1000, freq='T')
data = np.random.rand(1000, 3000)
columns = [f'col{n}' for n in range(3000)]
df = pd.DataFrame(data=data, index=index, columns=columns)

# 转换为Bokeh需要的格式
df = df.stack().reset_index()
df.rename(columns={'level_0':'x','level_1':'y', 0:'z'},inplace=True)
df.sort_values(by=['y'],inplace=True)
x = [date.to_datetime64().astype('M8[ms]').astype('O') for date in df.x.to_list()]
data = {
 'value': df.z.to_list(),
 'x': x,
 'y': df.y.to_list(),
 'date' : df.x.to_list()
}

# 创建绘图对象
p = figure(x_axis_type='datetime', y_range=columns, width=900, 
           tooltips=[("x", "@date"), ("y", "@y"), ("value", "@value")])
p.rect(x='x', y='y', width=60*1000, height=1, line_color=None, 
       fill_color=linear_cmap('value', 'Viridis256', low=df.z.min(), high=df.z.max()), 
       source=data)

# 自定义y轴动态刻度的JS回调
callback = CustomJS(args=dict(y_range=p.y_range), code="""
    const range = y_range;
    const start = Math.floor(range.start);
    const end = Math.ceil(range.end);
    const total = end - start;
    // 控制显示的刻度数量,这里设置最多显示50个
    const step = Math.max(Math.floor(total / 50), 1);
    const new_ticks = [];
    for (let i = start; i <= end; i += step) {
        new_ticks.push(range.factors[i]);
    }
    // 更新y轴刻度
    if (new_ticks.length > 0) {
        y_range.factors = new_ticks;
    }
""")

# 绑定回调到y轴的范围变化事件
p.y_range.js_on_change('start', callback)
p.y_range.js_on_change('end', callback)

show(p)

这个回调会在用户缩放或平移y轴时,自动计算可见范围,生成间隔合适的刻度标签,避免重叠。

方法2:结合Datashader + HoloViews实现高效渲染与动态刻度

既然你必须使用Datashader,HoloViews配合Datashader可以更高效处理大分类数据,同时自动处理动态刻度:

import holoviews as hv
from holoviews.operation.datashader import rasterize
hv.extension('bokeh')

# 复用之前的df数据(3000个分类)
heatmap = hv.HeatMap(df, kdims=['x', 'y'], vdims='z')
# 用Datashader光栅化处理大数据,动态适配视图
rasterized_heatmap = rasterize(heatmap, dynamic=True)

# 设置绘图选项,优化y轴显示
rasterized_heatmap.opts(
    width=900, 
    xaxis='datetime',
    yaxis='categorical',
    tools=['hover'],
    colorbar=True,
    cmap='Viridis256'
)

# 渲染显示
hv.render(rasterized_heatmap)

HoloViews的dynamic=True会自动根据视图的缩放级别调整渲染内容,配合Bokeh的分类轴,能自动过滤掉不可见的刻度标签,既避免重叠又保证性能。

额外优化建议

  • 若不需要显示所有分类的精确标签,可以设置y轴标签垂直排列,减少横向空间占用:p.yaxis.major_label_orientation = 1.0
  • 超大规模分类数据下,Datashader的光栅化是核心优化点,它会将大量分类数据转换为像素级渲染,避免Bokeh因渲染过多元素导致卡顿。

内容的提问来源于stack exchange,提问作者cadmaster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:02:23