Histogram

Dataviz logo representing a Histogram chart.

This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

This example explains how to plot the distribution of several groups, each distribution being drawn on its own pannel. This dataviz technique is called small multiples. It can be useful to compare the distribution of several items in a dataset.

A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

Useful links

Plot and code

If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

The distribution of several groups are displayed, one on each panel of the graphing window. It allows to compare the distributions.

Note that this works even if groups have very similar distributions as the bars won't overlap each other. It is thus a very good alternative to the histogram with multiple groups that would get unreadable in this condition.

Histogram representing the distribution of 4 groups in a dataset using the small multiple display. Made with react (rendering) and d3.js (scales)

The Data

The dataset used here is slightly different as the one used for the simple 1 group histogram.

An array is used, with each object in it providing the name (group property here) and the values of a group.

Here is a minimal example of the data structure:

const data = [
  {
    group: "A",
    values: [0, 0, 2, 2, 2, 0]
  },
  {
    group: "B",
    values: [0, 0, 2, 2, 2, 0]
  },
  ...
];

Color scale

There is a finite number of groups here. We need to assign a specific color to each group. This is called an ordinal scale and is implemented in the d3 scaleOrdinal function.

What's needed here is thus a list of colors to use (the range) and a list of group names: the domain.

To put it in a nutshell, that's how the color scale is implemented:

// List of arbitrary colors
const COLORS = ["#e0ac2b", "#e85252", "#6689c6", "#9a6fb0", "#a53253"];

// List of all group names
const allGroups = data.map((group) => group.group);

// Color scale
const colorScale = d3.scaleOrdinal<string>()
  .domain(allGroups)
  .range(COLORS);

It's fundamental to understand that with this code organization, d3.js will be used to prepare the svg circle, but it's react that will render them in the return() statement. We won't use d3 methods like append that you can find in usual d3.js examples.

Rendering

The Histogram component used to render each sub-panel is almost exactly the one presented in the histogram section of the gallery.

The only difference is that it receives 2 new properties. The color prop is computed in the parent component using the logic described above. The xRange prop is necessary to make sure all histograms have the same x axis, allowing to compare them efficiently.

Now, we just need to call the Histogram component for each group of the dataset and render tham in a grid layout as follow:

export const Histogram = ({ width, height, data }: HistogramProps) => {
  const allGroups = data.map((group) => group.group);
  const colorScale = d3.scaleOrdinal<string>().domain(allGroups).range(COLORS);

  const maxPerGroup = data.map((group) => Math.max(...group.values));
  const max = Math.max(...maxPerGroup);

  const numberOfColumn = 2;
  const numberOfRow = Math.ceil(allGroups.length / numberOfColumn);

  return (
    <div
      style={{
        width,
        height,
        display: "grid",
        gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
      }}
    >
      {data.map((group, i) => (
        <SingleHistogram
          key={i}
          width={width / numberOfColumn}
          height={height / numberOfRow}
          color={colorScale(group.group)}
          xRange={[0, max]}
          data={group.values}
        />
      ))}
    </div>
  );
};

Distribution

Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!