Holoviews+Bokeh绘制对数轴直方图无数据显示问题求助
解决Holoviews+Bokeh对数轴直方图无数据显示问题
问题现象
使用Holoviews搭配Bokeh后端绘制对数轴直方图时,设置logy=True后仅显示坐标轴无数据;手动设置ylim消除"Logarithmic axis range encountered value less than or equal to zero..."警告后,数据仍无法显示。
问题根源
Holoviews的Histogram在Bokeh后端默认使用VBar图形元素绘制,而VBar的底部默认从0开始。在对数轴下,log(0)无意义,导致Bokeh无法渲染出图形——即使设置了ylim排除0,底层图形元素的bottom值仍为0,依然无法正常显示数据。
解决方案
方案1:改用hv.Bars替代hv.Histogram
手动构造直方图的区间中心值和频率数据,用Bars组件绘制,通过设置bar_width匹配直方图区间宽度,效果与原生Histogram完全一致:
import holoviews as hv import numpy as np hv.extension('bokeh') tl = [2079, 76, 15022, 3475, 31550, 38, 564, 551, 77, 117, 8962, 14, 186, 691, 896, 2041, 1784, 5225, 2046, 15216, 176, 460, 219, 37903, 7806, 6325, 25396, 38016, 4154] frequencies, edges = np.histogram(tl, 20) # 计算每个区间的中心值 centers = (edges[:-1] + edges[1:]) / 2 # 构造Bars对象 bars_plot = hv.Bars((centers, frequencies), vdims='Frequency') # 设置绘图参数,bar_width设为区间宽度 bars_plot.opts( logy=True, height=400, width=400, ylim=(1E-1, 3E6), bar_width=edges[1] - edges[0] )
方案2:自定义绘图钩子修改Bokeh图形属性
通过Holoviews的hooks机制,修改Histogram对应的Bokeh渲染组件的bottom值,将其设为y轴下限,彻底避免log(0)的问题:
import holoviews as hv from holoviews.plotting.bokeh import HistogramPlot import numpy as np hv.extension('bokeh') # 定义钩子函数:修改bar的bottom值为y轴下限 def fix_log_histogram(plot, element): renderer = plot.handles['renderer'] y_min = plot.y_range.start renderer.glyph.bottom = y_min tl = [2079, 76, 15022, 3475, 31550, 38, 564, 551, 77, 117, 8962, 14, 186, 691, 896, 2041, 1784, 5225, 2046, 15216, 176, 460, 219, 37903, 7806, 6325, 25396, 38016, 4154] frequencies, edges = np.histogram(tl, 20) frequencies[frequencies <= 0] = .1 hist_plot = hv.Histogram((edges, frequencies)) # 应用钩子并设置绘图参数 hist_plot.opts( logy=True, height=400, width=400, ylim=(1E-1, 3E6), hooks=[fix_log_histogram] )
说明
两种方案都能有效解决对数轴下直方图不显示的问题:
- 方案1更直观,直接替换组件,无需修改底层渲染逻辑;
- 方案2保留了
hv.Histogram的原生结构,适合需要维持Histogram接口的场景。
内容的提问来源于stack exchange,提问作者MikeB2019x
相关产品推荐
相关产品推荐

