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

Chart.js中自定义坐标轴刻度的实现方法问询

关于Chart.js自定义坐标轴刻度的实现方案

完全可以通过自定义转换函数在Chart.js中实现类似matplotlib的自定义坐标轴刻度,包括Weibull、Normal(正态分布)这类概率刻度,核心是利用Chart.js提供的刻度转换接口。

实现核心逻辑

Chart.js允许通过ticks.transform和ticks.reverseTransform两个函数,分别实现原始数据到刻度值的正向转换,以及刻度值到原始数据的反向转换(用于tooltip、缩放等交互逻辑)。你需要基于目标分布的CDF(累积分布函数)和逆CDF(分位数函数)来编写这两个转换函数。

示例:正态分布(Normal)刻度实现

以下是基于正态分布Z分数的自定义y轴配置示例:

// 先实现误差函数及其逆函数(用于正态分布逆CDF计算)
function erf(x) {
  const a1 =  0.254829592;
  const a2 = -0.284496736;
  const a3 =  1.421413741;
  const a4 = -1.453152027;
  const a5 =  1.061405429;
  const p  =  0.3275911;
  const sign = x >= 0 ? 1 : -1;
  x = Math.abs(x);
  const t = 1.0 / (1.0 + p * x);
  const y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
  return sign * y;
}

function erfInv(x) {
  const a = 0.140012288686666;
  const b = 0.997788191211599;
  const c = 0.0344289899926483;
  const d = 0.00170814407474660;
  const e = 0.0000479966428378797;
  const f = 0.000000102934507663825;
  const g = 0.000000000105639711574206;
  const h = 0.0000000000000345017939721785;
  
  const sign = x >= 0 ? 1 : -1;
  const z = Math.abs(x);
  
  if (z >= 1) return sign * Infinity;
  if (z <= 0.7) {
    const y = z * z;
    return sign * z * (a + y * (b + y * (c + y * (d + y * (e + y * (f + y * (g + y * h)))))));
  } else {
    const y = Math.sqrt(-Math.log((1 - z) / 2));
    return sign * (y - (a + y * (b + y * (c + y * (d + y * (e + y * (f + y * (g + y * h)))))) / (1 + y * (b + y * (c + y * (d + y * (e + y * (f + y * (g + y * h)))))));
  }
}

// Chart.js配置
const chart = new Chart(document.getElementById('myChart'), {
  type: 'scatter',
  data: {
    datasets: [{
      data: [{x: 10, y: 0.1587}, {x: 20, y: 0.5}, {x: 30, y: 0.8413}] // y值为正态分布概率(0-1)
    }]
  },
  options: {
    scales: {
      y: {
        type: 'linear',
        ticks: {
          // 自定义刻度标签,显示Z分数
          callback: (value) => `${value}σ`,
          // 正向转换:概率值转Z分数
          transform: (value) => {
            return value < 0.5 ? -Math.sqrt(2) * erfInv(2 * value - 1) : Math.sqrt(2) * erfInv(2 * value - 1);
          },
          // 反向转换:Z分数转概率值
          reverseTransform: (value) => {
            return 0.5 * (1 + erf(value / Math.sqrt(2)));
          },
          stepSize: 1,
          min: -3,
          max: 3
        }
      }
    }
  }
});

Weibull刻度实现思路

Weibull分布的CDF为:F(x) = 1 - e^(-(x/λ)^k),逆CDF为:x = λ * (-ln(1-F(x)))^(1/k)(其中λ为尺度参数,k为形状参数,需根据你的数据集调整)。你可以参照上述正态刻度的方式,将transform和reverseTransform替换为Weibull分布对应的转换逻辑:

// 示例Weibull转换函数(假设λ=10,k=2)
const lambda = 10;
const k = 2;

// 正向转换:原始数据(失效时间x)转成概率值对应的刻度
transform: (xValue) => {
  return 1 - Math.exp(-Math.pow(xValue / lambda, k));
},
// 反向转换:刻度值(概率)转回原始失效时间x
reverseTransform: (probValue) => {
  return lambda * Math.pow(-Math.log(1 - probValue), 1/k);
}

关键注意事项

  • 自定义刻度需基于Chart.js的现有刻度类型(如linear)扩展,目前Chart.js没有原生支持Weibull或Normal概率刻度。
  • 确保transform和reverseTransform是严格单调函数,否则会导致渲染错乱或交互异常。
  • 可通过ticks.callback自定义刻度显示文本,比如直接显示概率值、分位数或分布参数相关标签。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:01:12