How to create a scatter plot using D3

A bit about D3

D3 is an interactive JavaScript library for data visualization. It uses Scalar Vector Graphics (SVG) coupled with HTML and CSS to display charts and figures illustrating the numeric data. You can also use D3 to make scatter plots. Here is a step-by-step guide on how to make a scatter plot using D3.

Step 1: Dataset

Before even starting to code, we need a data set to base our chart on. For this example, we will take a basic 2D array of random numbers. Our array is:

var dataset1 = [[90, 20], [20, 100], [66, 44], [53, 80], [24, 182], [80, 72], [10, 76], [33, 150], [100, 15]];

Step 2: D3 and SVG container

We need to import the D3 script using the src attribute and then initialize our SVG container with the appropriate width and height:

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="400"></svg>

Step 3: Set margin

To make the chart look more centered and clear, we need to set a margin for our SVG. We are making 4 variables; svg, margin, width, and height. svg is initialized with the 500px width and 400px height. These widths and heights are then adjusted according to the 200px margin:

var svg = d3.select("svg"),
            margin = 200,
            width = svg.attr("width") - margin,
            height = svg.attr("height") - margin

Step 4: Set scale

For discrete data visualization on the x-axis, we construct a Linear Scale or scaleLinear(). scaleLinear() uses the linear equation (y = mx + c) to interpolate domain and range across the axis:

var xScale = d3.scaleLinear().domain([0, 100]).range([0, width]),
            yScale = d3.scaleLinear().domain([0, 200]).range([height, 0]);

Step 5: Add text

We need to add title, x-axis label, and y-axis label to our plot. For this purpose, we will first append text to our svg, then set the position, style, and actual text attribute. To rotate our text for the y-axis, we will use transform and specify the angle of rotation:

// Step 5
        // Title
        svg.append('text')
        .attr('x', width/2 + 100)
        .attr('y', 100)
        .attr('text-anchor', 'middle')
        .style('font-family', 'Helvetica')
        .style('font-size', 20)
        .text('Scatter Plot');
        
        // X label
        svg.append('text')
        .attr('x', width/2 + 100)
        .attr('y', height - 15 + 150)
        .attr('text-anchor', 'middle')
        .style('font-family', 'Helvetica')
        .style('font-size', 12)
        .text('Independant');
        
        // Y label
        svg.append('text')
        .attr('text-anchor', 'middle')
        .attr('transform', 'translate(60,' + height + ')rotate(-90)')
        .style('font-family', 'Helvetica')
        .style('font-size', 12)
        .text('Dependant');

Step 6: Add axis

Now, we need to add both of the axes. For the x-axis, we call d3.axisBottom because we need to align it at the bottom of the canvas. For the y-axis, we call d3.axisLeft because we want to align it to the left of the canvas.

        g.append("g")
         .attr("transform", "translate(0," + height + ")")
         .call(d3.axisBottom(xScale));
        
        g.append("g")
         .call(d3.axisLeft(yScale));

Step 7: Scatter dots

This is where the magic happens. We need to add a dot for every coordinate in our dataset1. We supply dataset1 to the data attribute and then make a circle for each coordinate. The cx specifies the horizontal position of the circle, while cy specifies the vertical position of the circle. Moreover, the r specifies the radius of the circle. Then, we translate all the data points to match the translation of our axes. Finally, we color the data points red by giving the #CC0000 hex-code:

        svg.append('g')
        .selectAll("dot")
        .data(dataset1)
        .enter()
        .append("circle")
        .attr("cx", function (d) { return xScale(d[0]); } )
        .attr("cy", function (d) { return yScale(d[1]); } )
        .attr("r", 2)
        .attr("transform", "translate(" + 100 + "," + 100 + ")")
        .style("fill", "#CC0000");

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved