Drawing Separate Domains for Axes under Multiple S

2019-07-07 19:56发布

My intention is to draw multiple small barcharts in one svg with different domains, building upon the example.

The main problem I am stuck on seems to be the problem of extracting values for a particular key from the output of d3.nest and defining the domain corresponding to each key. The problem arises when plotting all the values, for which the dates are drawn in the domain. Since not each key has a value corresponding to all possible dates, there is a tail plotted on the right, which breaks the order. Could you please tell me how it can be fixed, how can the inputs without a corresponding output be removed from the plotted set of values?

Here is the result:

https://plnkr.co/edit/KUnMSfJwWan3JaIpZutZ/

The data is in the following form:

CSC     20160919    4.0
MAT     20160923    16.0

In the example sample of data given, there are two dates, and two dates are going to be plotted for each small subgraph. It would be great to separate the dates corresponding to a particular key in such a way that only those dates for which there is a corresponding score are plotted.

There is a deficiency: the domains must be separate, while in the example above they are not. Could you please tell me how I can plot the graphs for each key with the date corresponding to a particular key as defined in d3.nest?

The relevant part of the code seems to be here:

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

and here:

 svg.selectAll(".bar")
    .data(function(d) {return d.values;})
    .enter()
    .append("rect")
    .attr("class", "bar")
    .attr("x", function(d) { return x(d.date); })
    .attr("width", x.rangeBand())
    .attr("y", function(d) { return y(d.score); })
    .attr("height", function(d) { return height - y(d.score); })
    .attr("fill", function(d) {return color(d.score)})

APPENDIX

The following questions can be useful:

D3.js binding an object to data and appending for each key

X,Y domain data-binding in multiple grouped bar charts in d3.js

You can also find the following links helpful:

Grouped Bar Chart

Tutorial: Grouped Bar Chart

Grouping Data


HYPOTHESES


Can we nest the data twice, first by course, then by date, and then plot keys' keys on the axes? Is nesting the best way to approach the problem at all?

1条回答
Root(大扎)
2楼-- · 2019-07-07 20:27

Here is my solution (warning: I'm the first one to admit that my code is too complicated. Let's see if someone else comes with a simpler solution).

First, we create an empty object:

var xScale = {};

And populate this new object with two functions, one for each different scale.

courses.forEach(function(d) {
    xScale[d.key] = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1)
        .domain(d.values.map(function(e) {
            return e.date
        }));
});

After this, we'll have two different scales:

xScale.HIS//this is the scale for the first SVG
xScale.PHY//this is the scale for the second SVG

Now you can use those scales in your bars, but not directly. We have to define what scale is going to be used in what SVG.

To do that, firstly, we'll get the key property in the data for each SVG, and then using this value to access the correct object inside xScale, which contains the proper scale:

.attr("x", function(d) {
        var scale = d3.select(this.parentNode).datum().key;
        return xScale[scale](d.date);
    })
    .attr("width", function() {
        var scale = d3.select(this.parentNode).datum().key;
        return xScale[scale].rangeBand()
    })

The most complicated part is calling the axes. Here, we'll use each to call xAxis two times, using the first argument (the datum) to get the value of key:

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .each(function(d) {
        return d3.select(this).call(xAxis.scale(xScale[d.key]))
            .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.8em")
            .attr("dy", "-.55em")
            .attr("transform", "rotate(-90)");
    })

All together, this is your updated plunker: https://plnkr.co/edit/XFKzQm0zp0MkhzK4Qt5d?p=preview

查看更多
登录 后发表回答