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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 00:06:24