user3033194
user3033194

Reputation: 1821

Y Axis not displaying for scatter plot with d3 v4

I am trying to create a scatter plot with d3.js (v4). I am a newbie in d3, and thanks to the limited documentation of examples with v4, am struggling to create the plot (already have asked here once before). My code is given below:

const margin = { top: 100, right: 50, left: 50, bottom: 50};
const width = 1300 - margin.right - margin.left;
const height = 1250 - margin.top - margin.bottom;

d3.csv("http://localhost:9000/data.csv", (error, data) => {
    if (error) throw error;

    const x = (d) => d["Category"];

    const xScale = d3.scalePoint()
                     .domain(data.map((d) => d["Category"]))
                     .range([0, width]);
    const xMap = (d) => xScale(x(d));

    const xAxis = d3.axisBottom().scale(xScale);

    // Plotting Score 1 for now
    const y = (d) => d["Score 1"];
    const yScale = d3.scaleLinear()
                     .domain([0, d3.max(data, y)])
                     .range([height, 0]);

    const yMap = (d) => yScale(y(d))

    const yAxis = d3.axisLeft().scale(yScale);

    const svg = d3.select('body')
                  .append('svg')
                  .attr('width', width)
                  .attr('height', height)
                  .append('g')
                  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');


    svg.append('g')
       .attr('class', 'axis axis--x')
       .call(xAxis)
       .attr('transform', 'translate(0, 800)')
       .append('text')
       .attr('class', 'label')
       .attr('x', width)
       .attr('y', -6)
       .style('text-anchor', 'middle')
       .text('Category');

    svg.append('g')
       .attr('class', 'axis axis--y')
       .call(yAxis)
       .attr('transform', 'rotate(-90)')
       .attr('y', 0 - margin.left)
       .attr('x', 0 - (height/2))
       .attr("dy", "1em")
       .style('text-anchor', 'middle')
       .text('Score');

    svg.selectAll('circle')
       .data(data)
       .enter()
       .append('circle')
       .attr('class', 'dot')
       .attr('cx', xMap)
       .attr('cy', yMap)
       .attr('r', 3.5)
       .attr('fill', 'red');
});

A few lines of data.csv are given:

Name,Category,Score 1,Score 2,Score 3,Average score
A1_P1,A01,2.3,2.4,4.1,2.4
A2_P1,A02,1.4,1.5,2.4,1.5
A3_P1,A03,0.9,0.9,0.9,0.9
A4_P1,B01,1.5,1.5,1,1.5
A5_P1,B02,1.2,1.2,1.4,1.2
A6_P1,B03,1,1,1.1,1
A7_P1,C01,1.6,1.2,1,1.2
A8_P1,C02,1.2,1.2,0.9,1.2
A9_P1,C03,1.1,1.1,1,1.1
A10_P1,D01,1.5,1.6,1.1,1.5

The x-axis is showing (but not the 'Category' label), and even more importantly, the y-axis is not showing at all. The points themselves are being shown correctly, though. Does anyone know what is wrong with my y-axis setting and axis labels? Thanks in advance!

Upvotes: 0

Views: 553

Answers (1)

Mark
Mark

Reputation: 108512

When I start a new chart with d3, I find it best to start with a known simple set-up example to place my drawing g, axis, etc... This is my usual starting point.

That said, here's list of issues I see in your chart:

  1. Not placing x-axis dynamically.
  2. svg container is sized wrong and ends up on top of axis.
  3. Attempting to append a text axis label to y axis but you never actually append the text (and then apply attributes and styling to the axis itself instead of that missing text element).

Cleaning this all up looks like this:

<!DOCTYPE html>
<html>

<head>
  <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <script>
    const margin = {
      top: 100,
      right: 50,
      left: 50,
      bottom: 50
    };
    const width = 500 - margin.right - margin.left;
    const height = 500 - margin.top - margin.bottom;

    //d3.csv("data.csv", (error, data) => {
    //  if (error) throw error;
      
      var data = [{"Name":"A1_P1","Category":"A01","Score 1":"2.3","Score 2":"2.4","Score 3":"4.1","Average score":"2.4"},{"Name":"A2_P1","Category":"A02","Score 1":"1.4","Score 2":"1.5","Score 3":"2.4","Average score":"1.5"},{"Name":"A3_P1","Category":"A03","Score 1":"0.9","Score 2":"0.9","Score 3":"0.9","Average score":"0.9"},{"Name":"A4_P1","Category":"B01","Score 1":"1.5","Score 2":"1.5","Score 3":"1","Average score":"1.5"},{"Name":"A5_P1","Category":"B02","Score 1":"1.2","Score 2":"1.2","Score 3":"1.4","Average score":"1.2"},{"Name":"A6_P1","Category":"B03","Score 1":"1","Score 2":"1","Score 3":"1.1","Average score":"1"},{"Name":"A7_P1","Category":"C01","Score 1":"1.6","Score 2":"1.2","Score 3":"1","Average score":"1.2"},{"Name":"A8_P1","Category":"C02","Score 1":"1.2","Score 2":"1.2","Score 3":"0.9","Average score":"1.2"},{"Name":"A9_P1","Category":"C03","Score 1":"1.1","Score 2":"1.1","Score 3":"1","Average score":"1.1"},{"Name":"A10_P1","Category":"D01","Score 1":"1.5","Score 2":"1.6","Score 3":"1.1","Average score":"1.5"}];

      const x = (d) => d["Category"];

      const xScale = d3.scalePoint()
        .domain(data.map((d) => d["Category"]))
        .range([0, width]);
      const xMap = (d) => xScale(x(d));

      const xAxis = d3.axisBottom().scale(xScale);

      // Plotting Score 1 for now
      const y = (d) => d["Score 1"];
      const yScale = d3.scaleLinear()
        .domain([0, d3.max(data, y)])
        .range([height, 0]);

      const yMap = (d) => yScale(y(d))

      const yAxis = d3.axisLeft().scale(yScale);

      const svg = d3.select('body')
        .append('svg')
        .attr('width', width + margin.right + margin.left)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

      svg.append('g')
        .attr('class', 'axis axis--x')
        .call(xAxis)
        .attr('transform', 'translate(0,' + height + ')')
        .append('text')
        .attr('class', 'label')
        .attr('x', width)
        .attr('y', -6)
        .style('text-anchor', 'middle')
        .text('Category');

      svg.append('g')
        .attr('class', 'axis axis--y')
        .call(yAxis)
        .append("text")
        .attr('transform', 'rotate(-90)')
        .attr('y', 0 - margin.left)
        .attr('x', 0 - (height / 2))
        .attr("dy", "1em")
        .style('text-anchor', 'middle')
        .text('Score')
        .style('fill', 'black')

      svg.selectAll('circle')
        .data(data)
        .enter()
        .append('circle')
        .attr('class', 'dot')
        .attr('cx', xMap)
        .attr('cy', yMap)
        .attr('r', 3.5)
        .attr('fill', 'red');
        
    //});
  </script>
</body>

</html>

Upvotes: 1

Related Questions