block by curran 76d8a075dee5420c01e35742f8598332

Scatter Plot with Ordinal Axis

Full Screen

Part of the video course: D3.js in Motion.

An example of a scatter plot with an ordinal X axis.

The data shown here comes from Internet Top 20 Countries - Internet Users 2017 - Internet World Stats.

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <title>Top Internet Countries Visualization</title>
    <style>
      body {
        margin: 0px;
      }
      .domain {
        display: none;
      }
      .tick line {
        stroke: #C0C0BB;
      }
      .tick text {
        fill: #8E8883;
        font-size: 20pt;
        font-family: sans-serif;
      }
      .axis-label {
        fill: #635F5D;
        font-size: 40pt;
        font-family: sans-serif;
      }
    </style>
  </head>
  <body>
    <svg width="960" height="500"></svg>
    <script>

      const xValue = d => d.country;
      const xLabel = 'Country';
      const yValue = d => d.netUsers;
      const yLabel = 'Internet Users';
      const margin = { left: 150, right: 70, top: 20, bottom: 110 };

      const svg = d3.select('svg');
      const width = svg.attr('width');
      const height = svg.attr('height');
      const innerWidth = width - margin.left - margin.right;
      const innerHeight = height - margin.top - margin.bottom;

      const g = svg.append('g')
          .attr('transform', `translate(${margin.left},${margin.top})`);
      const xAxisG = g.append('g')
          .attr('transform', `translate(0, ${innerHeight})`);
      const yAxisG = g.append('g');

      xAxisG.append('text')
          .attr('class', 'axis-label')
          .attr('x', innerWidth / 2)
          .attr('y', 90)
          .text(xLabel);

      yAxisG.append('text')
          .attr('class', 'axis-label')
          .attr('x', -innerHeight / 2)
          .attr('y', -100)
          .attr('transform', `rotate(-90)`)
          .style('text-anchor', 'middle')
          .text(yLabel);

      const xScale = d3.scalePoint();
      const yScale = d3.scaleLinear();

      const xAxis = d3.axisBottom()
        .scale(xScale)
        .tickPadding(15)
        .tickSize(-innerHeight);

      const yTicks = 5;
      const yAxis = d3.axisLeft()
        .scale(yScale)
        .ticks(yTicks)
        .tickPadding(15)
        .tickFormat(d3.format('.0s'))
        .tickSize(-innerWidth);

      const row = d => {
        const netUsersWithCommas = d['Internet Users 31 Mar 2017'];
        return {
          country: d['Country or Region'],
          netUsers: +netUsersWithCommas.replace(/,/g, '')
        };
      };

      const top5 = data => data.slice(0, 5);

      d3.csv('data.csv', row, data => {
        data = top5(data);
        xScale
          .domain(data.map(xValue))
          .range([0, innerWidth]);

        yScale
          .domain(d3.extent(data, yValue))
          .range([innerHeight, 0])
          .nice(yTicks);

        g.selectAll('circle').data(data)
          .enter().append('circle')
            .attr('cx', d => xScale(xValue(d)))
            .attr('cy', d => yScale(yValue(d)))
            .attr('fill', 'black')
            .attr('fill-opacity', 0.6)
            .attr('r', 8);

        xAxisG.call(xAxis);
        yAxisG.call(yAxis);
      });
    </script>
  </body>
</html>

data.csv

#,Country or Region,"Population,2017 Est.",Internet Users 31 Mar 2017,Internet Penetration,Growth (*) 2000 - 2017,Facebook 30 June 2016
1,China,"1,388,232,693","731,434,547",52.7 %,"3,150.8 %","1,800,000"
2,India,"1,342,512,706","462,124,989",34.4 %,"9,142.5 %","157,000,000"
3,United States,"326,474,013","286,942,362",87.9 %,200.9 %,"201,000,000"
4,Brazil,"211,243,220","139,111,185",65.9 %,"2,682.2 %","111,000,000"
5,Indonesia,"263,510,146","132,700,000",50.4 %,"6,535.0 %","88,000,000"
6,Japan,"126,045,211","118,453,595",94.0 %,151.6 %,"26,000,000"
7,Russia,"143,375,006","104,553,691",72.9 %,"3,272.7 %","12,000,000"
8,Nigeria,"191,835,936","93,591,174",48.8 %,"46,695.6 %","16,000,000"
9,Germany,"80,636,124","71,727,551",89.0 %,198.9 %,"31,000,000"
10,Mexico,"130,222,815","69,915,219",53.7 %,"2,477.6 %","69,000,000"
11,Bangladesh,"164,827,718","66,965,000",40.6 %,"66,865.0 %","21,000,000"
12,United Kingdom,"65,511,098","60,273,385",92.0 %,291.4 %,"39,000,000"
13,Iran,"80,945,718","56,700,000",70.0 %,"22,580.0 %","17,200,000"
14,France,"64,938,716","56,367,330",86.8 %,563.1 %,"33,000,000"
15,Philippines,"103,796,832","54,000,000",52.0 %,"2,600.0 %","54,000,000"
16,Italy,"59,797,978","51,836,798",86.7 %,292.7 %,"30,000,000"
17,Vietnam,"95,414,640","49,741,762",52.1 %,"24,770.9 %","40,000,000"
18,Turkey,"80,417,526","46,196,720",57.4 %,"2,209.8 %","46,000,000"
19,"Korea, South","50,704,971","45,314,248",89.4 %,138.0 %,"17,000,000"
20,Thailand,"68,297,547","41,000,000",60.0 %,"1,682.6 %","41,000,000"