Why point closeness is differing from scatter plot to hexbin plot? - d3.js
Please look at Hexbin and scatterplots: http://imgur.com/a/2oR68
Why in Hexbinplot, points donot touch each other whereas in scatterplot it clearly touches the close points ?
I expected my hexbin plot comes up like this: https://bl.ocks.org/mbostock/4248145 but it didnot.
I am using d3.hexbin plugin.
The only code that is differing from Hexbin plot to scatter plot (I am dealing with same dataset) apart from little bit of scaling is:
For Hexbin:
var color = d3.scale.linear()
.range(["white", "steelblue"])
.interpolate(d3.interpolateLab);
var hexbin = d3.hexbin()
.extent([[0,0],[size - padding , padding]])
.radius();
hexbin.x(function(d,i){return x(subdata[0][i]);})
hexbin.y(function(d,i){return y(subdata[0][i]);})
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("class", "mesh")
.attr("width", w)
.attr("height", size);
svg.append("g")
.attr("clip-path", "url(#clip)")
.selectAll(".hexagon")
.data(hexbin(datum))
.enter()
.append("path")
.attr("class", "hexagon")
.attr("d", hexbin.hexagon())
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.style("fill", function(d) { return color(d.length); });
For scatterplot:
svg.selectAll("circle")
.data(datum)
.enter()
.append("circle")
.style("fill", "steelblue")
.attr("cx", function (d, i) {
return x(subdata[0][i]);
})
.attr("cy", function (d,i) {
return y(subdata[0][i]);
})
.attr("r", 3)
Where am i doing wrong ?
Edit1: Included some fraction of code under Hexbin
If you set...
.attr("d", hexbin.hexagon(5))
//radius value here ------^
..., the hexagons will touch only if you set the same value in the hexabin generator:
var hexbin = d3.hexbin()
.radius(5)//same value here
.extent([[0, 0], [width, height]]);
According to your result, I believe that was not the case. Thus, the solution can be simply removing that value:
.attr("d", hexbin.hexagon())
//no radius here --------^
Related
Text in the circle [duplicate]
This question already has answers here: Adding text to d3 circle (2 answers) Closed 3 years ago. I am writing a text element (x axis measure value) for each circle but even after showing text element in inspect in browser its not showing I have appended the text under circle given same x and y for the circle but its coming through !DOCTYPE html> <meta charset="utf-8"> <!-- Load d3.js --> <script src="https://d3js.org/d3.v4.js"></script> <!-- Create a div where the graph will take place --> <div id="my_dataviz"></div> <script> // set the dimensions and margins of the graph var margin = {top: 10, right: 30, bottom: 40, left: 100}, width = 460 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; // append the svg object to the body of the page var svg = d3.select("#my_dataviz") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Parse the Data d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum_header.csv", function(data) { // sort data data.sort(function(b, a) { return a.Value - b.Value; }); // Add X axis var x = d3.scaleLinear() .domain([0, 13000]) .range([ 0, width]); svg.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)) .selectAll("text") .attr("transform", "translate(-10,0)rotate(-45)") .style("text-anchor", "end"); // Y axis var y = d3.scaleBand() .range([ 0, height ]) .domain(data.map(function(d) { return d.Country; })) .padding(1); svg.append("g") .call(d3.axisLeft(y)) // Lines svg.selectAll("myline") .data(data) .enter() .append("line") .attr("x1", x(0)) .attr("x2", x(0)) .attr("y1", function(d) { return y(d.Country); }) .attr("y2", function(d) { return y(d.Country); }) .attr("stroke", "grey") // Circles -> start at X=0 svg.selectAll("mycircle") .data(data) .enter() .append("circle") .attr("cx", x(0) ) .attr("cy", function(d) { return y(d.Country); }) .attr("r", "7") .style("fill", "#69b3a2") .attr("stroke", "black") // Change the X coordinates of line and circle svg.selectAll("circle") .transition() .duration(2000) .attr("cx", function(d) { return x(d.Value); }) svg.selectAll("line") .transition() .duration(2000) .attr("x1", function(d) { return x(d.Value); }) // this is the line i have added at my end and it showing as well while i do the inspect element. svg.selectAll("circle") .append(Text) .attr("x", function (d) { return x(d.Value); }) .attr("y", function (d) { return y(d.Country); }) .text(function (d) { return d.Value}) .attr("font-family", "sans-serif") .attr("font-size", "6px") .attr("fill", "black") .style("text-anchor", "middle") }) </script> Would like to show measure value under circle so user dont have to guess the x axis. circle is at 13000 so it should show as 13 in circle divided by 1000
From what I can see there's a couple of things going on. Firstly, instead of: ... .append(Text) which is trying to pass in a variable called Text to the append function, it should be: ... .append('text') i.e. append an svg text element. However, this is still appending text elements to circle elements. If you look at the elements via Chrome Devtools, you can see that there will be a text element inside each circle element, which doesn't actually display anything. Instead, the label text needs to be rendered separately from the circles using something like. svg.selectAll("mytext") .data(data) .enter() .append('text') .attr("x", function (d) { return x(d.Value) + 10; }) .attr("y", function (d) { return y(d.Country) + 4; }) .text(function (d) { return d.Value}) .attr("font-family", "sans-serif") .attr("font-size", "10px") .attr("fill", "black") .style("text-anchor", "start") .style('opacity', 0) .transition() .delay(1500) .duration(500) .style('opacity', 1); I've made the font a bit bigger, and adjusted the x and y values and used text-anchor: start so that now the text appears just off the right of the circles. I've also put in a transition based on opacity with a delay so that the text only appears at the end of the circles' animation.
dataset created with d3.nest isn't drawing correctly
I am trying to visualize a dataset to see major players in the pangolin trade. I want each country to be part of a categorical scale on the y-axis, and the x-axis is the date, and I want each trade instance to be represented as a circle, with x being the date it happened, y being the position for that particular country, and r being the number of instances accumulated so far (represented in my data as r). Basically my data is from 2010 to 2016, and includes the country name where pangolins are either imported to or exported from, the count (accumulated trade instances up until this date), and the date (yyyy-mm-dd). Below is part of my data, which I store in the variable trade: [{"date":"2010-10-22","country":"Thailand","rank":4,"count":1},{"date":"2010-10-28","country":"Malaysia","rank":2,"count":1},{"date":"2010-11-8","country":"Thailand","rank":4,"count":2},{"date":"2010-11-18","country":"Nepal","rank":7,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":1},{"date":"2010-11-22","country":"China","rank":5,"count":2},{"date":"2010-11-27","country":"India","rank":1,"count":1},{"date":"2010-11-28","country":"India","rank":1,"count":2},{"date":"2010-11-28","country":"India","rank":1,"count":3},{"date":"2010-11-30","country":"India","rank":1,"count":4},{"date":"2010-12-17","country":"Malaysia","rank":2,"count":2},{"date":"2010-12-22","country":"Vietnam","rank":3,"count":1},{"date":"2011-01-3","country":"Nepal","rank":7,"count":2},{"date":"2011-02-12","country":"Myanmar","rank":8,"count":1},{"date":"2011-02-25","country":"Malaysia","rank":2,"count":3},{"date":"2011-02-26","country":"Malaysia","rank":2,"count":4},{"date":"2011-03-2","country":"South Africa","rank":18,"count":1},{"date":"2011-03-2","country":"Rwanda","rank":35,"count":1},{"date":"2011-03-2","country":"Mozambique","rank":22,"count":1},{"date":"2011-03-2","country":"Kenya","rank":12,"count":1},{"date":"2011-03-3","country":"China","rank":5,"count":3},{"date":"2011-02-21","country":"Vietnam","rank":3,"count":2},{"date":"2011-03-24","country":"Malaysia","rank":2,"count":5},{"date":"2011-04-4","country":"Malaysia","rank":2,"count":6},{"date":"2011-03-25","country":"India","rank":1,"count":5},{"date":"2011-03-26","country":"Malaysia","rank":2,"count":7},{"date":"2011-04-2","country":"Nepal","rank":7,"count":3},{"date":"2011-04-20","country":"Thailand","rank":4,"count":3},{"date":"2011-05-11","country":"China","rank":5,"count":4},{"date":"2011-05-11","country":"China","rank":5,"count":5},{"date":"2011-05-26","country":"Indonesia","rank":6,"count":1},{"date":"2011-05-26","country":"India","rank":1,"count":6},{"date":"2011-05-29","country":"Indonesia","rank":6,"count":2},{"date":"2011-06-6","country":"India","rank":1,"count":7},{"date":"2011-06-7","country":"Mozambique","rank":22,"count":2},{"date":"2011-06-5","country":"India","rank":1,"count":8},{"date":"2011-06-12","country":"Malaysia","rank":2,"count":8},{"date":"2011-06-13","country":"Singapore","rank":21,"count":1},{"date":"2011-06-14","country":"Malaysia","rank":2,"count":9},{"date":"2011-06-17","country":"India","rank":1,"count":9},{"date":"2011-06-19","country":"India","rank":1,"count":10},{"date":"2011-06-26","country":"Thailand","rank":4,"count":4},{"date":"2011-06-30","country":"India","rank":1,"count":11},{"date":"2011-07-4","country":"Malaysia","rank":2,"count":10},{"date":"2011-07-5","country":"Zimbabwe","rank":14,"count":1},{"date":"2011-07-12","country":"Indonesia","rank":6,"count":3},{"date":"2011-07-18","country":"Indonesia","rank":6,"count":4},{"date":"2011-07-27","country":"Nepal","rank":7,"count":4},{"date":"2011-08-16","country":"Nepal","rank":7,"count":5},{"date":"2011-08-19","country":"Namibia","rank":33,"count":1},{"date":"2011-08-23","country":"India","rank":1,"count":12},{"date":"2010-09-17","country":"Myanmar","rank":8,"count":2},{"date":"2011-09-1","country":"Zimbabwe","rank":14,"count":2},{"date":"2011-09-13","country":"Indonesia","rank":6,"count":5},{"date":"2011-09-13","country":"Malaysia","rank":2,"count":11},{"date":"2011-09-13","country":"Myanmar","rank":8,"count":3},{"date":"2011-09-21","country":"Malaysia","rank":2,"count":12},{"date":"2011-09-26","country":"Thailand","rank":4,"count":5},{"date":"2011-09-30","country":"Indonesia","rank":6,"count":6},{"date":"2011-10-1","country":"Sri Lanka","rank":19,"count":1},{"date":"2011-10-6","country":"India","rank":1,"count":13},{"date":"2011-10-7","country":"India","rank":1,"count":14},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":7},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":8},{"date":"2011-10-18","country":"Indonesia","rank":6,"count":9},{"date":"2011-10-22","country":"India","rank":1,"count":15},{"date":"2011-10-24","country":"India","rank":1,"count":16},{"date":"2011-11-28","country":"United States","rank":32,"count":1},{"date":"2011-12-15","country":"Vietnam","rank":3,"count":3},{"date":"2011-12-27","country":"Thailand","rank":4,"count":6},{"date":"2012-01-4","country":"Philippines","rank":15,"count":1},{"date":"2012-01-5","country":"Kenya","rank":12,"count":2},{"date":"2012-01-6","country":"Philippines","rank":15,"count":2},{"date":"2012-01-17","country":"Philippines","rank":15,"count":3},{"date":"2012-01-24","country":"China","rank":5,"count":6},{"date":"2012-02-22","country":"Malaysia","rank":2,"count":13},{"date":"2012-03-1","country":"Malaysia","rank":2,"count":14},{"date":"2012-03-19","country":"Pakistan","rank":11,"count":1},{"date":"2012-03-21","country":"Malaysia","rank":2,"count":15},{"date":"2012-03-23","country":"Vietnam","rank":3,"count":4},{"date":"2012-04-27","country":"Vietnam","rank":3,"count":5},{"date":"2012-04-23","country":"Belgium","rank":31,"count":1},{"date":"2012-06-7","country":"Thailand","rank":4,"count":7},{"date":"2012-06-7","country":"Thailand","rank":4,"count":8}]; and here is my code: var margin = {left:120, top:20, right:0, bottom:50}; var width = 1000; var height = 800; var data=trade; var tradeByCountry = d3.nest() .key(function(d) { return d.country; }) .entries(trade); console.log(tradeByCountry); tradeByCountry.forEach(function(country){ country['number']=country.values.length; console.log(country); }); var country_colors = ["#393b79","#5254a3", '#6b6ecf', '#9c9ede', '#637939', '#8ca252','#b5cf6b','#cedb9c', '#8c6d31','#bd9e39','#e7ba52','#e7cb94','#843c39','#ad494a','#d6616b','#e7969c','#7b4173','#a55194', '#ce6dbd','#de9ed6', '#9467bd', '#c5b0d5','#3182bd', '#6baed6','#17becf','#9edae5','#e6550d','#fd8d3c','#fdae6b', '#31a354','#74c476','#a1d99b','#d62728','#ff9896','#7f7f7f','#c7c7c7']; var colors = d3.scale.ordinal() .domain(d3.range(tradeByCountry.length)) .range(country_colors); tradeByCountry.sort(function(x, y){ return d3.descending(x.number, y.number); }) var countriesArray = []; tradeByCountry.forEach(function(country){ countriesArray.push(country.key); }); console.log(countriesArray); var x = d3.time.scale() .rangeRound([0, width]); var y = d3.scale.linear() .range([height, 0]); var timeFormat = d3.time.format("%Y-%m-%d"); x.domain([timeFormat.parse('2010-10-22'),timeFormat.parse('2016-12-30')]); y.domain(countriesArray); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", width) .attr("y", -6) .style("text-anchor", "end") .text("date"); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "translate(35,-25)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("countries"); svg.selectAll(".dot") .data(tradeByCountry) .enter().append("circle") .attr("class", "dot") .attr("r", 7) .attr("cx", function(d) { return 0; }) .attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) .style("fill", function(d,i) { return colors(i); }); svg.selectAll("text.labels") .data(tradeByCountry) .enter() .append("text") .text(function(d) {return d.key}) .attr("x", 0) .attr("y", function(d,i) { return (height/tradeByCountry.length)*i; }) .attr("transform", "translate(-120,5)") .attr("fill",function(d,i) { return colors(i); }); svg.selectAll('.line') .data(tradeByCountry) .enter().append('line') .attr("x1", 0) // x position of the first end of the line .attr("y1",function(d,i) { return (height/tradeByCountry.length)*i; }) .attr("x2", width) // x position of the second end of the line .attr("y2", function(d,i) { return (height/tradeByCountry.length)*i; }) .style("stroke",function(d,i) { return colors(i); }) .attr("id", function(d){return d.key}); //PROBLEM HERE!!!!!!!!!!! var g = svg .selectAll("g") .data(tradeByCountry) .enter().append("g") .selectAll(".dot") .data(function(d) {return d.values;}) .enter().append("circle") .attr("id", function(d){ return d.count;}) .attr("r", function(d){return d.count;}) .attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); }) .attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) .style("fill", function(d,i) { return colors(i); }); I am having trouble specifically at the very last part of my code, where I can't get all the circles to draw and not in the correct r, as I would like r to increase as the trade accumulates over time for a country, instead it seems that r is different according to country:
Two things, firstly in your example .selectAll("g") at the point you mark as having the error was picking up g elements in the axes, so the first few countries weren't getting their data displayed. This doesn't appear to be the case in your screenshot but it was happening given the code you posted, so I just qualified those gs with the .country class. The second thing, and what was causing your specific problem was this line: .attr("cy", function(d,i) { return (height/tradeByCountry.length)*i; }) I'm guessing you thought the index variable i here was still tied to the tradeByCountry array, which it would have been after selectAll("g.country").data(tradebyCountry) but at this point we've now made a nested selection .selectAll(".dot") on d.values for each country's data so i is now indexing those list of values. So that line of code above will take the values for each country and separate them all vertically, always starting from the top row - when in fact you want them on the same line, just separated by country. What you wanted (I = India, M = Malaysia, T = Thailand) I--- I0 I1 I2 M--- M0M1 M2 T--- T0 T1 T2 What you were getting I--- I0 M0 T0 M--- M1 I1 T1 T--- I2 T2 M2 This was also hidden by the fact .attr("fill") also had the same mistake so the colours on each row were consistent (I've used d.rank instead to fix it). Solution 1: To make sure the values stay on the same correct line use i before you do the nested selection so it still refers to the countries like this, which will offset each g element by the correct amount: .attr("transform", function(d,i) { return "translate(0,"+(height/tradeByCountry.length)*i+")"; }) and simply set cy to be zero for everything you add to this g element and they'll all be in a straight line (and on the right line) Full code at the PROBLEM HERE! stage: var g = svg .selectAll("g.country") .data(tradeByCountry) .enter().append("g") .attr("class", "country") .attr("transform", function(d,i) { return "translate(0,"+(height/tradeByCountry.length)*i+")"; }) .selectAll(".dot") .data(function(d) {return d.values;}) .enter().append("circle") .attr("class", "dot") .attr("id", function(d){ return d.country+"_"+d.date+"_"+d.count;}) .attr("r", function(d){ return d.count;}) .attr("cx", function(d,i) { console.log (d.date);return (x(timeFormat.parse(d.date))); }) .attr("cy", function(d,i) { return 0; }) .style("fill", function(d,i) { return colors(d.rank); }); http://jsfiddle.net/d4typ567/1/ Solution 2: It's also the case that d3 maintains a parent index variable for nested selections (usually denoted ii) that can be passed into most d3 .attr and .style functions, so you could do .attr("cy", function(d,i, ii) { return (height/tradeByCountry.length)*ii; }) instead, but offsetting the g element is only 1 operation whereas this is done for every circle. Remember to do the same for the color (fill) function.
Triangle scatter plot with D3.js
I was trying to create a scatter plot with triangle points following this example. But I got all the triangles locate at the top left corner, which looks so weired. Can anyone help to fix and explain? code: svg.selectAll(".point") .data(data) .enter() .append("path") .attr("class", "point") .attr("d", d3.svg.symbol().type("triangle-up")) .attr({ cx: function(d) { return x(d.quality); }, cy: function(d) { return y(d.Type); }, r: 8 }) .style("fill", function(d){return color(d.Type);});
You can't use cx and cy for anything other than circles. Use .attr("transform", function(d) { return "translate(" + x(d.quality) + "," + y(d.Type) + ")"; })
D3 vertical line graph
I have a line (& area) graph which works ok, when horizontal. But I really need it to be vertical, to stand up. I have tried all kinds of changes to the existing code. Mostly with some strange results. Here’s the code (modified it a bit). Is there a way to change it to make the graph vertical?: var x = d3.scale.linear().domain([1, itemCount]).range([0, width]); var y = d3.scale.linear().domain([0, maxValue]).rangeRound([height, 0]); // Set up linar x and y axis. var xAxis = d3.svg.axis().scale(x).ticks(10); var yAxis = d3.svg.axis().scale(y).ticks(2).orient("left"); // Line graph. line = d3.svg.line() .interpolate("basis") .x(function (d) { return x(d.x); }) .y(function (d) { return y(d.y); }); // Create SVG element. var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); // X-Axis, to bottom. svg.append("svg:g") .attr("class", "axis") .attr("transform", "translate(1," + height + ")") .call(xAxis); //Y-Axis svg.append("svg:g") .attr("class", "axis") .attr("transform", "translate(40, 1)") .call(yAxis); // Horizontal axis guide lines. svg.selectAll("line.y") .data(y.ticks(5)) .enter() .append("line") .attr("x1", 0) .attr("x2", width) .attr("y1", y) .attr("y2", y) .style("stroke", "#000000") .style("stroke-opacity", 0.1); // Vertical axis guide lines. svg.selectAll("line.x") .data(y.ticks(5)) .enter() .append("line") .attr("x1", x) .attr("x2", x) .attr("y1", 0) .attr("y2", this.heightInside - pushDown) .style("stroke", "#000000") .style("stroke-opacity", 0.1); // Set up domains. Nice ensures the domains ends on nice round values. x.domain([dataValues[0].x, dataValues[dataValues.length - 1].x]).nice(); y.domain([d3.min(dataValues, function (d) { return (d.y); }), d3.max(dataValues, function (d) { return (d.y); })]) .nice(); // Draw line on graph. svg.append("svg:path") .attr("class", "line") .attr("d", line(dataValues)) .style("stroke", function(d) { return colors[i]; }); // Marks. svg.selectAll("circle_" + i) .data(dataValues) .enter() .append("circle") .style("fill", function(d) { return _this.colors[i]; }) .attr("r", 4) .attr('cx', function (d) { return x(d.x); }) .attr('cy', function (d) { return y(d.y); });
Zooming bar-graph with d3.js
I am trying to create a bar graph with a time scale where its possible to zoom into any time period. I was able to create the zooming functionality for my x-axis(time scale) however my data (in this case rects) doesn't zoom along with my axis. Here is a simplified version of my graph: http://jsfiddle.net/gorkem/Mf457/5/embedded/result/ As you can see I can zoom in to my x-axis but the bars do not zoom along. and here is the jfiddle link: http://jsfiddle.net/gorkem/Mf457/6/ var y = d3.scale.linear().domain([0, max_val]).range([graph_height, 0]); var x = d3.time.scale().domain([minDate, maxDate]).range([0, graph_width]); var chart = d3.select(location).append("svg") .attr("class", "chart") .attr("width", graph_width+20) .attr("height", graph_height+20) .call(d3.behavior.zoom().x(x).scaleExtent([1, 8]).on("zoom", zoom)); var lines = chart.selectAll("line"); var lines_y = lines .data(x.ticks(5)) .enter().append("line") .attr("x1", x) .attr("x2", x) .attr("y1", function (d) {return graph_height - 20 - d;}) .attr("y2", graph_height) .style("stroke", "#ccc"); var lines_x = lines .data(y.ticks(10)) .enter().append("line") .attr("x1", 0) .attr("x2", graph_width) .attr("y1", y) .attr("y2", y) .style("stroke", "#ccc"); xAxis = d3.svg.axis().scale(x); yAxis = d3.svg.axis().scale(y).orient("left"); chart.append("svg:g") .attr("class", "xaxis") .attr("transform","translate(0,300)") .call(xAxis); chart.append("svg:g") .attr("class", "yaxis") .attr("transform", "translate(25,0)") .call(yAxis); var rect = chart.selectAll("rect") .data(data) .enter().append("rect") .attr("x", function (d,i) {return x(new Date(d["date"]))+20; }) .attr("y", function (d,i) { return graph_height - (d["num"] *v_scale);}) .attr("width", x(new Date(data[1]["date"]))) .attr("height", function (d,i) {return d["num"]*v_scale;}); rect.call(d3.behavior.zoom().x(x).scaleExtent([1, 8]).on("zoom", zoom)); function zoom() { chart.select(".xaxis").call(xAxis); chart.select(".yaxis").call(yAxis); } } I feel like I should be adding more functionality to my zoom function for the function to be effective on bars(rects). I would really appreciate any help.
Using 'selectAll', I've applied the scaling and translation to each bar respectively, restricting both scale and translation to the x-axis only. function zoom() { chart.select(".xaxis").call(xAxis); chart.select(".yaxis").call(yAxis); chart.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)"); } This works equally well with a single path element, which is what I was trying to figure out when I stumbled upon your question.
I'm wondering the same thing, so at least know you're in good company. Here's my current approach. First of all, I can't generate a plot from your code and the links don't send me to anything useful -- no chart renders. So I can't help with your specific problem. However, there is an example that has zoomable rectangles here: http://bl.ocks.org/1962173. I'm currently going through it and deleting unnecessary elements and seeing if I can make it work. Hopefully this helps!