plotly / plotly/plotly.js

add native range charts

Aperta
#7,288 2 commenti 2 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

feature P3
Lingua principale
JavaScript
Stelle
18.3k
Fork
2k
Merge medio
2g 12h
PR unite (30g)
28

Descrizione

MinutePhysics called us out (by name!) for not having native support for range charts: https://www.youtube.com/watch?v=5zBg9pH_6bE

However, to be clear, it is possible to build this chart type in Plotly using the base attribute for bar charts and doing a bit of data preparation.

Here's a live demo of a custom range chart and our built-ins: https://codepen.io/ndrezn/pen/XJrWboB

Code snippet
/**
 * Creates a range bar chart using Plotly.js.
 *
 * @param {Object} data - The dataset, with keys as categories (e.g., cities) and values as arrays of measurements.
 * @param {Array} labels - The labels for each measurement (e.g., temperature metrics).
 * @param {string} containerId - The ID of the HTML container to render the chart.
 * @param {string} title - The title of the chart.
 */
function rangeChart(data, labels, containerId, title) {
  const categories = Object.keys(data); // Extract categories (e.g., cities)

  // Generate bar traces for each label
  const barTraces = labels.map((label, index) => {
    const bases = categories.map((category) =>
      index === 0 ? data[category][index] : data[category][index - 1]
    ); // base, i.e. the previous value
    const heights = categories.map(
      (category) => data[category][index] - bases[categories.indexOf(category)]
    ); // Height relative to the base, i.e. the current value
    return {
      x: categories,
      y: heights, // Bar heights
      base: bases, // Starting points for each bar
      name: label,
      type: "bar"
    };
  });

  // Layout for the chart
  const layout = {
    title: title,
    barmode: "overlay", // Overlapping bars to show ranges
    xaxis: { title: "Category" },
    yaxis: { title: "Value" }
  };

  // Render the chart
  Plotly.newPlot(containerId, barTraces, layout);
}

const ranges = {
  Ontario: [-9, 3, 8, 13, 27],
  England: [3, 8, 12, 16, 24],
  Kentucky: [-3, 8, 14, 20, 30]
};

const labels = [
  "Winter mean low",
  "Annual mean low",
  "Annual mean",
  "Annual mean high",
  "Summer mean high"
];

rangeChart(
  ranges,
  labels,
  "rangePlot",
  "Temperature Ranges in Three Londons (range)"
);

Image

That being said, having this chart-type built in would be great. The mental gymnastics are a bit tricky to get a true range chart working correctly.

Here are the built-in ways to achieve a similar chart:

Code snippet
// Data for the three Londons
const ranges = {
  Ontario: [-9, 3, 8, 13, 27],
  England: [3, 8, 12, 16, 24],
  Kentucky: [-3, 8, 14, 20, 30]
};

const labels = [
  "Winter mean low",
  "Annual mean low",
  "Annual mean",
  "Annual mean high",
  "Summer mean high"
];
const cities = Object.keys(ranges);

// Scatter plot traces
const scatterTraces = labels.map((label, index) => ({
  x: cities,
  y: cities.map((city) => ranges[city][index]),
  mode: "markers",
  name: label,
  type: "scatter"
}));

const scatterLayout = {
  title: "Temperature Ranges in Three Londons (scatter)",
  xaxis: { title: "City" },
  yaxis: { title: "Temperature" }
};

Plotly.newPlot("scatterPlot", scatterTraces, scatterLayout);

// Bar plot traces
const barTraces = labels.map((label, index) => ({
  x: cities,
  y: cities.map((city) => ranges[city][index]),
  name: label,
  type: "bar"
}));

const barLayout = {
  title: "Temperature Ranges in Three Londons (overlay)",
  barmode: "overlay",
  xaxis: { title: "City" },
  yaxis: { title: "Temperature" }
};

Plotly.newPlot("barPlot", barTraces, barLayout);

// Bar plot traces
const stackedBarTraces = labels.map((label, index) => ({
  x: cities,
  y: cities.map((city) => ranges[city][index]),
  name: label,
  type: "bar"
}));

const stackedBarLayout = {
  title: "Temperature Ranges in Three Londons (stacked)",
  barmode: "stack",
  xaxis: { title: "City" },
  yaxis: { title: "Temperature" }
};

Plotly.newPlot("stackedBarPlot", stackedBarTraces, stackedBarLayout);

However, these aren't quite right.

  • The scatter plot is most legible, but doesn't depict a range
  • The overlaid bar shows the right data, but because the base of all positive points is 0, they actually overlap on top of each other. We want the base to he previous, and for England, we want the base to be 3, not 0.
  • The stacked bar chart looks right at first glance, but it's actually summing all the temperatures (and of course, the base for England is at 0, not 3. And the negative values stack a bit weirdly.

Image

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Non sono identificati file sorgente, test o punti di ingresso. Inizia dall’esempio personalizzato di range-chart dell’issue e confronta il suo comportamento con gli approcci scatter, overlaid-bar e stacked-bar elencati; il lavoro è completato quando Plotly.js dispone del supporto nativo per range-chart e gestisce correttamente le basi diverse da zero e negative.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
javascript
Ambito
data-visualization
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.