Bokeh如何在X轴与Y轴显示负对数刻度?
问题解答
Bokeh原生的log轴类型确实只支持正值,因为对数函数的数学定义域是正实数,官方实现会自动过滤掉非正的数据点,所以你的负数据会消失,没办法直接用原生log轴实现正负都有的对数刻度。
不过可以通过自定义对称对数变换来实现需求,核心思路是对负数取绝对值后计算对数,再保留符号,轴刻度显示对应的正负对数标记。以下是适配你的代码的实现方案:
实现步骤
1. 定义对称对数变换
使用CustomJSTransform创建自定义变换函数,处理正负值的对数转换:
from bokeh.models import CustomJSTransform, ColumnDataSource # 对称对数变换:处理0和正负值,避免对数奇点 sym_log_transform = CustomJSTransform( v_func=""" return xs.map(x => { if (x === 0) return 0; const sign = x > 0 ? 1 : -1; return sign * Math.log10(Math.abs(x) + 1); }); """, inverse_v_func=""" return xs.map(x => { if (x === 0) return 0; const sign = x > 0 ? 1 : -1; return sign * (Math.pow(10, Math.abs(x)) - 1); }); """ )
注:如果你的数据里没有0,也可以去掉+1直接用Math.log10(Math.abs(x))。
2. 修改图表初始化
放弃原生log轴类型,改用线性轴并绑定自定义变换:
p = figure( height=600, sizing_mode="stretch_width", tools=TOOLS, tooltips=TOOLTIPS, toolbar_location="above", x_axis_label="Profit [%]", y_axis_label="Profit Growth [%]" ) # 给坐标轴应用对称对数变换 p.xaxis.major_label_orientation = 3.14 / 4 p.xaxis[0].formatter = NumeralTickFormatter(format="0") p.yaxis[0].formatter = NumeralTickFormatter(format="0") p.grid.grid_line_alpha = 0.3 p.x_range.transform = sym_log_transform p.y_range.transform = sym_log_transform
3. 调整辅助线与数据绘制
自定义变换会自动处理原始数据的转换,所以直接用原始极值绘制辅助线即可:
low_x = fundamental['Profit [%]'].min() high_x = fundamental['Profit [%]'].max() low_y = fundamental['Profit Growth [%]'].min() high_y = fundamental['Profit Growth [%]'].max() # 绘制中心坐标轴 p.line(x=(low_x, high_x), y=(0, 0), color='gray', line_width=1) p.line(x=(0, 0), y=(low_y, high_y), color='gray', line_width=1) # 正负区间标记线 p.line(x=(low_x, 0), y=(0, 0), color='red', line_width=2, line_dash='dashed') p.line(x=(0, 0), y=(low_y, 0), color='red', line_width=2, line_dash='dashed') p.line(x=(0, high_x), y=(0, 0), color='green', line_width=2, line_dash='dashed') p.line(x=(0, 0), y=(0, high_y), color='green', line_width=2, line_dash='dashed') # 示例:绘制原始数据散点,变换自动生效 p.circle(x='Profit [%]', y='Profit Growth [%]', source=ColumnDataSource(fundamental), size=6) show(p)
关键说明
- 对称对数变换既保留了对数轴压缩极值的特性,又能完整展示正负数据,不需要剔除异常值。
- 轴刻度显示的是原始数据的数值,符合金融数据的阅读习惯,不会出现对数刻度的抽象标记。
内容的提问来源于stack exchange,提问作者Rakshasha Medhi
相关产品推荐
相关产品推荐

