user3033194
user3033194

Reputation: 1831

Create scatter plot with ordinal scale in d3 version 4

I am trying to create a scatter plot with d3 v4. I have been through many examples for v3 and v4, but there are not many explaining how to create a graph with an ordinal scale in v4. My code is given below:

const margin = { top: 100, right: 50, left: 50, bottom: 50};
const width = 1500 - 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.scaleOrdinal()
                     .domain(data.map((d) => d["Category"]))
                     .range([0, width]);


    const xAxis = d3.axisBottom(xScale);

    const y = (d) => d["Score"];
    const yScale = d3.scaleLinear()
                     .range([height, 0]);
    yScale.domain([d3.min(data, y)-1, d3.max(data, y)+1]);

    const yAxis = d3.axisLeft(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', 'x axis')
       .call(xAxis)
       .attr('transform', 'translate(0, 400)')
       .append('text')
       .attr('class', 'label')
       .attr('x', width)
       .attr('y', -6)
       .style('text-anchor', 'end')
       .text('Category');

    svg.append('g')
       .attr('class', 'y axis')
       .call(yAxis)
       .attr('class', 'label')
       .attr('transform', 'rotate(-90)')
       .attr('y', 6)
       .attr('dy', '.71rem')
       .text('Score');

    svg.selectAll('circle')
       .data(data)
       .enter()
       .append('circle')
       .attr('class', 'dot')
       .attr('cx', (d) => {
           console.log(x(d));
           return x(d);
       })
       .attr('cy', (d) => y(d))
       .attr('r', 5)
       .attr('fill', 'red');
});

CSS:

.axis path,
.axis line {
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
}

My problem is that nothing is really appearing. I get this error message for every x value I want to show on the ordinal scale:

Error: <circle> attribute cx: Expected length, "B10".

The y-axis does not appear at all, and the x-axis appears without the scale and the 'Category' text. Please help!

Upvotes: 1

Views: 999

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102218

Don't use a scaleOrdinal here, since you have a continuous range.

Use a scalePoint instead. According to the API:

Point scales are a variant of band scales with the bandwidth fixed to zero. Point scales are typically used for scatterplots with an ordinal or categorical dimension.

Thus, it should be:

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

Besides that, you should use the scale to set the cx attribute, not the "x" const:

.attr('cx', (d) => xScale(d.Category))

Upvotes: 2

Related Questions