Small multiple for area chart





If you have several groups to display on your area chart, it is possible to stack them. But it makes it harder to study the evolution of each group separately. Using small multiple is a very good alternative, and this post describes how to implement it in d3.js. This example works with d3.js v4 and v6


Area chart section

Steps:

  • This is an advance technique. You probably need to understand how to build a basic area chart first, and then have a look to the lineplot with several groups to understand how nesting works.

  • Instead of building one main svg area as usual, many svg areas are created: one per group

  • To do so, data is bound to each svg area. This is very handy: each time a component will be created, it will be done for each subchart

  • ToDo: improve explanation
|
<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v6.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<script>

// set the dimensions and margins of the graph
var margin = {top: 30, right: 0, bottom: 30, left: 50},
    width = 210 - margin.left - margin.right,
    height = 210 - margin.top - margin.bottom;

//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/5_OneCatSevNumOrdered.csv", function(data) {

  // group the data: I want to draw one line per group
  var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
    .key(function(d) { return d.name;})
    .entries(data);

  // What is the list of groups?
  allKeys = sumstat.map(function(d){return d.key})

  // Add an svg element for each group. The will be one beside each other and will go on the next row when no more room available
  var svg = d3.select("#my_dataviz")
    .selectAll("uniqueChart")
    .data(sumstat)
    .enter()
    .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform",
            "translate(" + margin.left + "," + margin.top + ")");

  // Add X axis --> it is a date format
  var x = d3.scaleLinear()
    .domain(d3.extent(data, function(d) { return d.year; }))
    .range([ 0, width ]);
  svg
    .append("g")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x).ticks(3));

  //Add Y axis
  var y = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) { return +d.n; })])
    .range([ height, 0 ]);
  svg.append("g")
    .call(d3.axisLeft(y).ticks(5));

  // color palette
  var color = d3.scaleOrdinal()
    .domain(allKeys)
    .range(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628','#f781bf','#999999'])

    // Draw the line
    svg
      .append("path")
        .attr("fill", function(d){ return color(d.key) })
        .attr("stroke", "none")
        .attr("d", function(d){
          return d3.area()
          .x(function(d) { return x(d.year) })
          .y0(y(0))
          .y1(function(d) { return y(+d.n) })
            (d.values)
        })

  // Add titles
  svg
    .append("text")
    .attr("text-anchor", "start")
    .attr("y", -5)
    .attr("x", 0)
    .text(function(d){ return(d.key)})
    .style("fill", function(d){ return color(d.key) })

})
</script>
<script>

// set the dimensions and margins of the graph
const margin = {top: 30, right: 0, bottom: 30, left: 50},
      width = 210 - margin.left - margin.right,
      height = 210 - margin.top - margin.bottom;

//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/5_OneCatSevNumOrdered.csv").then( function(data) {

  // group the data: I want to draw one line per group
  const sumstat = d3.group(data, d => d.name); // d3.group function allows to group the calculation per level of a factor

  // What is the list of groups?
  const allKeys = data.map(d => d.name);

  // Add an svg element for each group. The will be one beside each other and will go on the next row when no more room available
  const svg = d3.select("#my_dataviz")
    .selectAll("uniqueChart")
    .data(sumstat)
    .join("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform",`translate(${margin.left},${margin.top})`);

  // Add X axis --> it is a date format
  const x = d3.scaleLinear()
    .domain(d3.extent(data, d => d.year))
    .range([ 0, width ]);
  svg
    .append("g")
    .attr("transform", `translate(0, ${height} )`)
    .call(d3.axisBottom(x).ticks(3));

  //Add Y axis
  const y = d3.scaleLinear()
    .domain([0, d3.max(data, d => +d.n )])
    .range([ height, 0 ]);
  svg.append("g")
    .call(d3.axisLeft(y).ticks(5));

  // color palette
  const color = d3.scaleOrdinal()
    .domain(allKeys)
    .range(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628','#f781bf','#999999'])

    // Draw the line
    svg
      .append("path")
        .attr("fill", d => color(d[0]))
        .attr("stroke", "none")
        .attr("d", d => {
          return d3.area()
          .x(d => x(d.year))
          .y0(y(0))
          .y1(d => y(+d.n))
            (d[1])
        })

  // Add titles
  svg
    .append("text")
    .attr("text-anchor", "start")
    .attr("y", -5)
    .attr("x", 0)
    .text(d => d[0])
    .style("fill", d => color(d[0]))

})
</script>

Related blocks →