Reputation: 1831
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
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