4

I make a scatterplot using d3.js where the points are arranged by their name and an accompanying number. The data that is plotted would look like this:

name,   group, number
"AB",   "A",   0.5
"ABC",  "A",   10.0
"BC",   "B",   3.0
"BCD",  "B",   5.0
"BCDE", "B",   0.3
"CD",   "C",   1.6
"DE",   "D",   1.5

What I want to achieve.

What I want to achieve is a plot where the points are scattered on the x axis according to their name, but the x axis should display the group once per group and a tick between different groups.

The result should look like this: enter image description here


What I have so far.

I do have a y and an x axis, the ticks and labels are not shown. In principle, the axes are created using the code below (example for the x axis):

var x = d3.scale.ordinal()
    .rangeBands([0, 400]);
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickValues(0) // hide ticks
    .tickFormat(""); // hide labels

The domain is derived from the name column:

x.domain(data.map(function(d) { return d.name; })); 

And appended to to actual svg:

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + 400 + ")")
    .call(xAxis)

This code results in the following plot: plot with empty axes


What I tried.

I tried with adding a second x axis by simply repeating the steps that were used to create the first x axis described above. I just renamed x to x2, made ticks and labels visible, and derived the domain not from d.name but from d.group. The complete code is here. Naturally, this distributes the labels and ticks along the whole x axis and does not incorporate the group information. plot with labels from group


Question.

How can I scatter the labels and ticks of the x axis according to the group column from the data?

user1251007
  • 15,891
  • 14
  • 50
  • 76

1 Answers1

2

Naive approach

One simplistic, but perhaps not desired way of handling this would be by using tickFormat to simply repeat the group value for each ordinal value on the scale:

var lkUp = {};
chartData.forEach(function(d) { lkUp[d.name] = {group: d.group}; });
xAxis.tickFormat(function(d) { return lkUp[d].group; });

Naive grouping

Working example: http://bl.ocks.org/jsl6906/64de7c45e4484114334b

Drawing from scratch

If you move outside of trying to use D3's axis component, you can draw these groups separately, i.e.:

//'chartGroups' is an array of calculated groups, with start and end coordinates
var chartGroups = svg.selectAll("g.chartGroup").data(chartGroups)
  .enter().append("g").attr(..);
chartGroups.append("text").attr(..);
chartGroups.append("path").attr(..);

Drawing from Scratch

Working example: http://bl.ocks.org/jsl6906/a8a4dd54f3d8de6a7aae

Community
  • 1
  • 1
Josh
  • 5,460
  • 31
  • 38
  • Thanks Josh! This works like a charm! One thing though, I'm trying to rotate the new group labels. How can I do this? I thought about using `.atrr("transform", "rotate(-90)"`, but that does not work as expected when I add this right before this line: `.text(function(d) { return d.group; });`. Instead, the whole block of labels is rotated so that is along the y axis. Any Idea? Or should I ask a new question for that? – user1251007 Sep 23 '14 at 14:13
  • To make the text rotate as you'd expect, you'll probably want to change the `text-anchor` style of that text, i.e.: `.style("text-anchor", "start")` or `"end"`, the default value for scales is `"middle"` – Josh Sep 27 '14 at 03:26