score:3

The easiest way to achieve this is setting two scales, one ordinal scale for the x axis, like `scalePoint`, and one linear scale for the y axis.

This is the x scale:

``````var xScale = d3.scalePoint()
.domain(data.map(function(d){return d.A}))
.range([50, width-50])
``````

And this the y scale:

``````var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d){return d.B})*1.1])
.range([height - 50, 10]);
``````

Here is a demo:

``````var data = [{A: "groupA", B: 10},
{A: "groupB", B: 20},
{A: "groupA", B: 30},
{A: "groupC", B: 5},
{A: "groupB", B: 11}]

var width = 400, height = 200;

var svg = d3.selectAll("body")
.append("svg")
.attr("width", width)
.attr("height", height);

var color = d3.scaleOrdinal(d3.schemeCategory10)
.domain(data.map(function(d){return d.A}));

var xScale = d3.scalePoint()
.domain(data.map(function(d){return d.A}))
.range([50, width-50])

var yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d){return d.B})*1.1])
.range([height - 50, 10]);

var circles = svg.selectAll(".circles")
.data(data)
.enter()
.append("circle")
.attr("r", 8)
.attr("cx", function(d){ return xScale(d.A)})
.attr("cy", function(d){ return yScale(d.B)})
.attr("fill", function(d){ return color(d.A)});

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

svg.append("g").attr("transform", "translate(0,150)")
.attr("class", "xAxis")
.call(xAxis);

svg.append("g")
.attr("transform", "translate(50,0)")
.attr("class", "yAxis")
.call(yAxis);``````
``<script src="https://d3js.org/d3.v4.min.js"></script>``

PS: since one scale here is ordinal (qualitative), this is not technically a scatterplot.