Dinosaurius
Dinosaurius

Reputation: 8628

How to put two 1D frequency distribution charts next to each other?

I want to create two 1D frequency distribution charts (see this example) and put them one next to other (in a single row).

Here is my fiddle.

The problem is that only the first 1D chart appears, while the second one is invisible.

Should I create a separate svg element for each bar or can I add different bars to the same svg?

var bar1 = svg1.selectAll(".bar")
    .data(data1)
    .enter().append("g")
    .attr("class", "bar1")
    .attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });

var bar2 = svg2.selectAll(".bar")
    .data(data2)
    .enter().append("g")
    .attr("class", "bar1")
    .attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });

Upvotes: 0

Views: 58

Answers (1)

Mark
Mark

Reputation: 108537

This line:

.attr("transform", "translate(" + 100+margin.left + "," + margin.top + ")");

is causing you troubles. JavaScript parses this left to right and it treates the whole thing as string concatenation, so it evaluates to:

<g transform="translate(10030,10)">

What you probably meant is:

.attr("transform", "translate(" + (100+margin.left) + "," + margin.top + ")");

That will evaluate (100+margin.left) as a numerical expression before the string concatenation.


Cleaned up example:

var values1 = [48,119,92,53,58,84,56,54,141,176,23,78,55,32,53,71,45,85,41,74,80]
var values2 = [18,19,12,13,18,14,16,14,14,16,23,18,15,12,13,11,15,15,11,14,8]

// A formatter for counts.
var formatCount = d3.format(",.0f");

var margin = {top: 10, right: 30, bottom: 30, left: 30},
    width = 300 - margin.left - margin.right,
    height = 100 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .domain([0, 150])
    .range([0, width]);

// Generate a histogram using sixty uniformly-spaced bins.
var data1 = d3.layout.histogram()
    .bins(x.ticks(60))
    (values1);

var data2 = d3.layout.histogram()
    .bins(x.ticks(60))
    (values2);    

var opacity = d3.scale.linear()
    .domain([0, d3.max(data1, function(d) { return d.y; })])
    .range(["white", "blue"]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");


<!-- The 1st 1D histogram -->

var svg1 = d3.select("body").append("svg").style('float','left')
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var bar1 = svg1.selectAll(".bar")
    .data(data1)
    .enter().append("g")
    .attr("class", "bar1")
    .attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });
    
bar1.append("rect")
    .attr("x", 0)
    .attr("width", x(data1[0].dx) )
    .attr("height", 50)
    .style("fill", function(d){ return opacity(d.y)})

svg1.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);


<!-- The 2nd 1D histogram -->

var svg2 = d3.select("body").append('div').append("svg").style('float','left')
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var bar2 = svg2.selectAll(".bar")
    .data(data2)
    .enter().append("g")
    .attr("class", "bar2")
    .attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; });
    
bar2.append("rect")
    .attr("x", 0)
    .attr("width", x(data2[0].dx) )
    .attr("height", 50)
    .style("fill", function(d){ return opacity(d.y)})

svg2.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
body {
  font: 10px sans-serif;
}

.bar rect {
  fill: steelblue;
  shape-rendering: crispEdges;
}

.bar text {
  fill: #fff;
}

.axis path, .axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
<body></body>
<script src="https://d3js.org/d3.v3.min.js"></script>

Upvotes: 1

Related Questions