ROC Curve with AUC — Apache ECharts

A Receiver Operating Characteristic (ROC) curve visualizes the performance of a binary classifier by plotting the True Positive Rate (TPR) against the False Positive Rate (FPR) at various classification thresholds. The Area Under the Curve (AUC) provides a single metric summarizing model performance, where 1.0 indicates perfect classification and 0.5 represents random guessing.

ROC Curve with AUC rendered with Apache ECharts

Renders

JavaScript source (Apache ECharts)

// anyplot.ai
// roc-curve: ROC Curve with AUC
// Library: echarts 6.1.0 | JavaScript 22.23.2
// Quality: 87/100 | Created: 2026-09-05

//# anyplot-orientation: square
const t = window.ANYPLOT_TOKENS;

// --- Data (in-memory, deterministic) ----------------------------------------
// Two binary classifiers scored on the same 500-sample holdout set (disease
// diagnosis: positive = disease present). Model scores are simulated via a
// tiny fixed-seed LCG so the ROC staircase is reproducible across renders.
function makeLcg(seed) {
  let state = seed >>> 0;
  return function random() {
    state = (state * 1664525 + 1013904223) >>> 0;
    return state / 4294967296;
  };
}

function sampleScores(seed, mean, stdDev, count) {
  const random = makeLcg(seed);
  return Array.from({ length: count }, () => {
    const u1 = Math.max(random(), 1e-9);
    const u2 = random();
    const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
    return mean + z * stdDev;
  });
}

function rocCurve(negScores, posScores) {
  const P = posScores.length;
  const N = negScores.length;
  const thresholds = Array.from(new Set([...negScores, ...posScores])).sort(
    (a, b) => b - a,
  );

  const points = [[0, 0]];
  for (const threshold of thresholds) {
    const tp = posScores.filter((s) => s >= threshold).length;
    const fp = negScores.filter((s) => s >= threshold).length;
    points.push([fp / N, tp / P]);
  }
  points.push([1, 1]);
  return points.sort((a, b) => a[0] - b[0]);
}

function auc(points) {
  let area = 0;
  for (let i = 1; i < points.length; i++) {
    const [x0, y0] = points[i - 1];
    const [x1, y1] = points[i];
    area += ((x1 - x0) * (y0 + y1)) / 2;
  }
  return area;
}

const SAMPLE_SIZE = 250;
const negScoresGbm = sampleScores(1001, 0, 1, SAMPLE_SIZE);
const posScoresGbm = sampleScores(2002, 2.4, 1.05, SAMPLE_SIZE);
const negScoresLogReg = sampleScores(3003, 0, 1, SAMPLE_SIZE);
const posScoresLogReg = sampleScores(4004, 1.15, 1.2, SAMPLE_SIZE);

const gbmPoints = rocCurve(negScoresGbm, posScoresGbm);
const logRegPoints = rocCurve(negScoresLogReg, posScoresLogReg);
const gbmAuc = auc(gbmPoints);
const logRegAuc = auc(logRegPoints);

const gbmName = `Gradient Boosting (AUC = ${gbmAuc.toFixed(2)})`;
const logRegName = `Logistic Regression (AUC = ${logRegAuc.toFixed(2)})`;
const randomName = "Random classifier (AUC = 0.50)";

// --- Init --------------------------------------------------------------------
const chart = echarts.init(document.getElementById("container"));

// --- Option --------------------------------------------------------------------
chart.setOption({
  animation: false,
  color: t.palette,
  backgroundColor: "transparent",
  title: {
    text: "roc-curve · javascript · echarts · anyplot.ai",
    left: "center",
    top: 24,
    textStyle: { color: t.ink, fontSize: 22 },
  },
  legend: {
    top: 84,
    left: "center",
    itemWidth: 24,
    itemHeight: 3,
    textStyle: { color: t.inkSoft, fontSize: 15 },
  },
  tooltip: {
    trigger: "axis",
    axisPointer: { type: "cross" },
  },
  grid: {
    left: 150,
    top: 150,
    width: 900,
    height: 900,
  },
  xAxis: {
    type: "value",
    name: "False Positive Rate",
    nameLocation: "middle",
    nameGap: 40,
    nameTextStyle: { color: t.ink, fontSize: 16 },
    min: 0,
    max: 1,
    interval: 0.2,
    axisLabel: { color: t.inkSoft, fontSize: 14 },
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { show: true, lineStyle: { color: t.grid } },
  },
  yAxis: {
    type: "value",
    name: "True Positive Rate",
    nameLocation: "middle",
    nameGap: 55,
    nameTextStyle: { color: t.ink, fontSize: 16 },
    min: 0,
    max: 1,
    interval: 0.2,
    axisLabel: { color: t.inkSoft, fontSize: 14 },
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { show: true, lineStyle: { color: t.grid } },
  },
  series: [
    {
      name: randomName,
      type: "line",
      data: [
        [0, 0],
        [1, 1],
      ],
      showSymbol: false,
      lineStyle: { color: t.inkSoft, width: 2, type: "dashed" },
      itemStyle: { color: t.inkSoft },
      emphasis: { disabled: true },
      z: 1,
    },
    {
      name: gbmName,
      type: "line",
      step: "end",
      data: gbmPoints,
      showSymbol: false,
      lineStyle: { color: t.palette[0], width: 3.5 },
      itemStyle: { color: t.palette[0] },
      areaStyle: { color: t.palette[0], opacity: 0.12 },
      markArea: {
        silent: true,
        label: { show: false },
        itemStyle: { color: t.palette[0], opacity: 0.07 },
        data: [[{ coord: [0, 1] }, { coord: [0.22, 0.82] }]],
      },
      z: 3,
    },
    {
      name: logRegName,
      type: "line",
      step: "end",
      data: logRegPoints,
      showSymbol: false,
      lineStyle: { color: t.palette[1], width: 3.5 },
      itemStyle: { color: t.palette[1] },
      z: 2,
    },
  ],
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/roc-curve/echarts/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "roc-curve",
  "language": "javascript",
  "library": "echarts",
  "page": "https://anyplot.ai/roc-curve/javascript/echarts",
  "hub": "https://anyplot.ai/roc-curve",
  "code_json": "https://api.anyplot.ai/specs/roc-curve/echarts/code",
  "spec_json": "https://api.anyplot.ai/specs/roc-curve",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/roc-curve/javascript/echarts/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/roc-curve/javascript/echarts/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/roc-curve/javascript/echarts/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/roc-curve/javascript/echarts/plot-dark.html",
  "quality_score": 87.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of ROC Curve with AUC on anyplot.ai.

Other implementations