I'm attempting a choropleth map of US Counties, and am essentially using Mike Bostock's example from here https://bl.ocks.org/mbostock/4060606 I am using education instead of unemployment, but otherwise it's the same. I'd like to add just one more piece to it and have the county name display along with the rate. However, when I call the county name, I get "undefined" returned. To be clear 'rate' returns just fine, 'county' shows up undefined. Can anyone help? Thanks!
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.counties {
fill: none;
/*stroke: black;*/
}
.states {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var Bachelor = d3.map();
var path = d3.geoPath();
var x = d3.scaleLinear()
.domain([0, 70])
.rangeRound([600, 860]);
var color_domain = [10, 20, 30, 40, 50, 60, 70]
var ext_color_domain = [10, 20, 30, 40, 50, 60, 70]
var color = d3.scaleThreshold()
.domain(color_domain)
.range([" #85c1e9", "#5dade2", "#3498db", "#2e86c1", "#2874a6", " #21618c"," #1b4f72"]);
var g = svg.append("g")
.attr("class", "key")
.attr("transform", "translate(0,40)");
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[1];
return d;
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); });
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("% of Adults with Bachelor's or higher");
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(function(x, i) { return i ? x : x; })
.tickValues(color.domain()))
.select(".domain")
.remove();
d3.queue()
.defer(d3.json, "https://d3js.org/us-10m.v1.json")
.defer(d3.tsv, "Bachelor2.tsv", function(d) { Bachelor.set(d.id, d.rate, d.county); })
.await(ready);
function ready(error, us) {
if (error) throw error;
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("fill", function(d) { return color(d.rate = Bachelor.get(d.id)); })
.attr("d", path)
.append("title")
.text(function(d) { return (d.county +" " d.rate +"%"); });
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
}
</script>
There are two problems in your code.
The first problem in your code lies here:
Bachelor.set(d.id, d.rate, d.county);
In both javascript maps and D3 maps (which are slightly different), you cannot set two values for the same key. Therefore, the syntax has to be:
map.set(key, value)
Let's show it.
This works, setting the value "bar" to "foo":
var myMap = d3.map();
myMap.set("foo", "bar");
console.log(myMap.get("foo"))
<script src="https://d3js.org/d3.v4.min.js"></script>
However, this will not work:
var myMap = d3.map();
myMap.set("foo", "bar", "baz");
console.log(myMap.get("foo"))
<script src="https://d3js.org/d3.v4.min.js"></script>
As you can see, the value "baz" was not set.
That was assuming that country is a property in your Bachelor2.tsv file. And that brings us to the second problem:
In your paths, this is the data:
topojson.feature(us, us.objects.counties).features
If you look at your code, you set a property named rate (using your map) to that data...
.attr("fill", function(d) { return color(d.rate = Bachelor.get(d.id)); })
//you set 'rate' to the datum here --------^
...but you never set a property named country. Therefore, there is no such property for you to use in the callbacks.
As explained above, you cannot set it using the same map you used to set the rate. A solution is using an object instead. Alternatively, you could use two maps, which seems to be the fastest option.
Related
I am new to D3 library for Data Visualisation.
I am trying to create a vertical legend.
And below is my implementation.
We can see there is huge gap between the column of rects(are on extreme right) and vertical ticks.
I guess, I am missing something in g.call because of my limited knowledge.
Can someone please, what mistake I am doing ?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.counties {
fill: none;
}
.states {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
</style>
<svg width="1260" height="600"></svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
</head>
<body>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var poverty = d3.map();
var path = d3.geoPath();
var x = d3.scaleLinear()
//.domain([1, 10])
.domain([1, 10])
.rangeRound([600, 860]);
//console.log("x:==>", x);
var y = d3.scaleLinear()
//.domain([1, 10])
.domain([1, 10])
.rangeRound([15, 160]);
var color = d3.scaleThreshold()
//.domain(d3.range(2, 10))
.domain(d3.range(2, 10))
.range(d3.schemeBlues[9]);
var g = svg.append("g")
.attr("class", "key")
//.attr("transform", "translate(0,40)");
.attr("transform", "translate(350,40)");
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[1];
return d;
}))
.enter().append("rect")
/*.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); })*/
.attr("height", 15)
.attr("x", 600)
.attr("y", function(d) { return y(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); }) ;
g.append("text")
.attr("class", "caption")
/*.attr("x", x.range()[0])
.attr("y", -6)*/
.attr("x",x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Poverty rate");
g.call(d3.axisRight(y)
//.tickSize(13)
.tickFormat(function(x, i) { return i ? 2*x : 2*x + "%"; })
.tickValues(color.domain()))
.select(".domain")
.remove();
var promises = [
d3.json("https://snippetnuggets.com/TnD/us.json"),
d3.csv("https://snippetnuggets.com/TnD/county_poverty.csv", function(d) { poverty.set(d.id, +d.rate); console.log(d); })
]
Promise.all(promises).then(ready)
function ready([us]) {
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("fill", function(d) { return color(d.rate = poverty.get(d.id)); })
.attr("d", path)
.append("title")
.text(function(d) { return d.rate + "%"; });
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
}
</script>
</body>
</html>
Your large gap between your axis ticks/labels and legend rects is there because you set x to 600 on your rects (.attr("x", 600)), which means you position the rects 600 pixels to the right, relative to the rects' parent container.
What happens is that first you append a g element, which you translate 350 pixels horizontally to the right (and 40 vertically downwards). When you later append rects to this g element, the rects are positioned relative to the g elements position. Therefore, setting the x attribute on the rects to 600 means in effect that you position the rects 950 pixels (350 + 600) to the right of the left side of the SVG.
To fix this, you should lower your x attribute on the rects. Negative values are valid too.
Check the reference for SVG rect elements here: SVG
I don't know why, according to the topojson version (may be) I have:
TypeError: t is undefined
An explanation could be nice! (I use the last version of topojson.)
Here an example of TypeError is undefined (pointing to topojson file)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://unpkg.com/d3#5.0.0/dist/d3.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
</head>
<body>
<svg width="960" height="600"></svg>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var unemployment = d3.map();
var path = d3.geoPath();
var x = d3.scaleLinear()
.domain([1, 10])
.rangeRound([600, 860]);
var color = d3.scaleThreshold()
.domain(d3.range(2, 10))
.range(d3.schemeBlues[9]);
var g = svg.append("g")
.attr("class", "key")
.attr("transform", "translate(0,40)");
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[1];
return d;
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); });
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Unemployment rate");
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(function(x, i) { return i ? x : x + "%"; })
.tickValues(color.domain()))
.select(".domain")
.remove();
var files = ["https://d3js.org/us-10m.v1.json", "unemployment.tsv"];
var promises1 = d3.json("https://d3js.org/us-10m.v1.json");
var promises2 = d3.tsv("unemployment.tsv");
Promise.all([promises1, promises2]).then(function(us){
console.log(us[0]);
console.log(us[1]);
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us[0].objects.counties).features)
.enter().append("path")
.attr("fill", function(d) { return color(d.rate = unemployment.get(d.id)); })
.attr("d", path)
.append("title")
.text(function(d) { return d.rate + "%"; });
svg.append("path")
.datum(topojson.mesh(us, us[0].objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
});
</script>
</body>
</html>
My code : https://plnkr.co/edit/EzcZMSEQVzCt4uoYCLIc?p=info
Original (d3js v4 + Topojson v2) : https://bl.ocks.org/mbostock/4060606
Here an another example of TypeError is undefined (pointing to topojson file)
My code : https://plnkr.co/edit/o1wQX3tvIDVxEbDtdVZP?p=preview
The two examples have two separate issues in relation to topojson.
In the first example you update where the topojson is held from us to us[0] due to the change in how files are fetched. However, you haven't quite updated the code to reflect this change:
In Original: .data(topojson.feature(us, us.objects.counties).features)
In Question: .data(topojson.feature(us, us[0].objects.counties).features)
And fixed: .data(topojson.feature(us[0], us[0].objects.counties).features)
Updated plunkr.
However, the issue in the second example is a little different.
topojson.feature requires two parameters, a topology and an object. The topology is the variable holding the json, which you have correct. However, the object is not arcs. The variable holding the topojson has a property called objects, and in that there will always be at least one property representing a feature collection (states, counties, etc). This object (or one of these objects) is what we want.
Here is a snippet of your topojson:
... "objects":{"dep_GEN_WGS84_UTF8":{"type":"GeometryCollection","geometries":[{"arcs ..."
We want topojson.feature(data,data.objects.dep_GEN_WGS84_UTF8).
If making topojson with tools such as mapshaper, the object we want to display is the same as the name of the file used to create it. Generally, a quick word search through the topojson for "object" will also get you to the proper object pretty quick.
The arcs property in a topojson is convenient storage for the pieces that make up the features, not the features themselves.
Updated plunkr.
In both cases the topology parameter passed to topojson.feature won't contain the specified features, generating the same error.
I am using D3.js to showcase my data. However, I am unable to get two different objects to not overlap. For example, the code below shows a line graph and a bar graph. I am using code from https://github.com/d3/d3/wiki/Gallery for this example to show my issue. The line graph code is from https://bl.ocks.org/mbostock/3883245. The bar graph code is from https://bl.ocks.org/mbostock/3885304. I tried using as shown in this example http://www.d3noob.org/2013/07/arranging-more-than-one-d3js-graph-on.html, but it did not work. I also made sure they both used the same version of d3.js. The data is from two tsv files that are on the links above for the line and bar graph. Any help would be appreciated!
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="lineg"></div>
<div id="barg"></div>
<lineg width="960" height="500"></lineg>
<barg width="960" height="500"></barg>
<script>
var svga = d3.select("#lineg"),
margina = {top: 20, right: 20, bottom: 30, left: 40},
widtha = +svga.attr("width") - margina.left - margina.right,
heighta = +svga.attr("height") - margina.top - margina.bottom;
var xa = d3.scaleBand().rangeRound([0, widtha]).padding(0.1),
ya = d3.scaleLinear().rangeRound([heighta, 0]);
var ga = svga.append("g")
.attr("transform", "translate(" + margina.left + "," + margina.top + ")");
d3.tsv("bardata.tsv", function(d) {
d.frequency = +d.frequency;
return d;
}, function(error, data) {
if (error) throw error;
xa.domain(data.map(function(d) { return d.letter; }));
ya.domain([0, d3.max(data, function(d) { return d.frequency; })]);
ga.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + heighta + ")")
.call(d3.axisBottom(xa));
ga.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(ya).ticks(10, "%"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
ga.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return xa(d.letter); })
.attr("y", function(d) { return ya(d.frequency); })
.attr("width", xa.bandwidth())
.attr("height", function(d) { return heighta - ya(d.frequency); });
});
</script>
<script>
var svgb = d3.select("barg"),
marginb = {top: 20, right: 20, bottom: 30, left: 50},
widthb = +svgb.attr("width") - marginb.left - marginb.right,
heightb = +svgb.attr("height") - marginb.top - marginb.bottom,
gb = svgb.append("g").attr("transform", "translate(" + marginb.left + "," + marginb.top + ")");
var parseTime = d3.timeParse("%d-%b-%y");
var xb = d3.scaleTime()
.rangeRound([0, widthb]);
var yb = d3.scaleLinear()
.rangeRound([heightb, 0]);
var line = d3.line()
.x(function(d) { return xb(d.date); })
.y(function(d) { return yb(d.close); });
d3.tsv("linedata.tsv", function(d) {
d.date = parseTime(d.date);
d.close = +d.close;
return d;
}, function(error, data) {
if (error) throw error;
xb.domain(d3.extent(data, function(d) { return d.date; }));
yb.domain(d3.extent(data, function(d) { return d.close; }));
gb.append("g")
.attr("transform", "translate(0," + heightb + ")")
.call(d3.axisBottom(xb))
.select(".domain")
.remove();
gb.append("g")
.call(d3.axisLeft(yb))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Price ($)");
gb.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
});
</script>
In your code barg and lineg are just divs:
<div id="lineg"></div>
<div id="barg"></div>
Instead of that, they should be SVG elements, like this:
<svg id="barg" width="960" height="500"></svg>
<svg id="lineg" width="960" height="500"></svg>
Or, alternatively, append an SVG in your selection:
var svga = d3.select("#lineg").append("svg");
var svgb = d3.select("#barg").append("svg");
However, in that case, you cannot use the getters to get the width and height of the SVGs.
Finally, there is no HTML tag named <lineg> or <barg>.
I have a map created from a geojson using d3.js lib and I colored randomly different states of map. Now I want to get color of a state when I hover it in mouseover function :
var lastColor;
function mouseover(d) {
lastColor = d.color; //This code is not works for me
d3.select(this)
.style('fill', 'orange')
.style('cursor', 'pointer');
}
function mouseout(d) {
d3.select(this)
.style('fill', lastColor);
}
Is it possible to get the color from d so that I return to this color when I mouseout from this state ?
In the on function, this refers to the DOM element. So, if you set the colour using style, you can get the same colour using style as a getter:
.on('mouseover', function(d){
console.log(d3.select(this).style("fill"))//'style' as a getter
});
Check this demo, hovering over the states (I set the colours using Math.random()):
var width = 720,
height = 375;
var colorScale = d3.scale.category20();
var projection = d3.geo.albersUsa()
.scale(800)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("https://dl.dropboxusercontent.com/u/232969/cnn/us.json", function(error, us) {
svg.selectAll(".state")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.style('fill', function(d) {
return colorScale(Math.random() * 20)
})
.attr('class', 'state')
.on('mouseover', function(d) {
console.log(d3.select(this).style("fill"))
});
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("d", path)
.attr("class", "state-boundary");
});
.land {
fill: #222;
}
.county-boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
.state-boundary {
fill: none;
stroke: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
EDIT: I have to confess that I read only the title of your question when you first posted it ("How to find the color of a state in mouseover"). Now, after properly reading the text of your post, I reckon the solution is even easier (btw, "Preserve the color of a state" is indeed a better title to the question).
If you set the colour using any property in the data (let's say, id):
.style('fill', function(d){
return colorScale(d.id)
})
You can simply set it again in the "mouseout":
.on('mouseover', function(d) {
d3.select(this).style("fill", "orange")
}).on("mouseout", function(d) {
d3.select(this).style('fill', function(d) {
return colorScale(d.id)
})
});
Check this other demo:
var width = 720,
height = 375;
var colorScale = d3.scale.category20();
var projection = d3.geo.albersUsa()
.scale(800)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("https://dl.dropboxusercontent.com/u/232969/cnn/us.json", function(error, us) {
svg.selectAll(".state")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.style('fill', function(d){
return colorScale(d.id)
})
.attr('class', 'state')
.on('mouseover', function(d){
d3.select(this).style("fill", "orange")
}).on("mouseout", function(d){
d3.select(this).style('fill', function(d){
return colorScale(d.id)
})});
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("d", path)
.attr("class", "state-boundary");
});
.land {
fill: #222;
}
.county-boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
.state-boundary {
fill: none;
stroke: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
Hello I currently have a stacked bar chart in d3,js that currently won't transition.
The chart is able to update but unfortunately no transition :(
I am under the feeling that there is a 1 line fix to this.
Please help!!!
Took this from
http://bl.ocks.org/anotherjavadude/2940908
<!DOCTYPE html>
<html>
<head>
<title>Simple Stack</title>
<script src="http://d3js.org/d3.v3.js"></script>
<style>
svg {
border: solid 1px #ccc;
font: 10px sans-serif;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="viz"></div>
<script type="text/javascript">
var w = 960,
h = 500
// create canvas
var svg = d3.select("#viz").append("svg:svg")
.attr("class", "chart")
.attr("width", w)
.attr("height", h )
.append("svg:g")
.attr("transform", "translate(10,470)");
x = d3.scale.ordinal().rangeRoundBands([0, w-800])
y = d3.scale.linear().range([0, h-100])
z = d3.scale.ordinal().range(["blue", "lightblue"])
// console.log("RAW MATRIX---------------------------");
// 3 columns: ID,c1,c2
var matrix = [
[ 1, 5871, 8916]
];
// console.log(matrix)
var matrix2 = [
[ 1, 21, 800]
];
function rand_it(x){
return Math.floor((Math.random() * x) + 1);
}
function render(matrix){
var t = d3.transition()
.duration(300);
// remove
svg.selectAll("g.valgroup")
.remove();
svg.selectAll("rect")
.transition(t)
.remove();
var remapped =["c1","c2"].map(function(dat,i){
return matrix.map(function(d,ii){
return {x: ii, y: d[i+1] };
})
});
console.log("NEW ONE !!!\n",matrix[0]);
// console.log("LAYOUT---------------------------");
var stacked = d3.layout.stack()(remapped)
x.domain(stacked[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(stacked[stacked.length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each column.
var valgroup = svg.selectAll("g.valgroup")
.data(stacked)
.enter().append("svg:g")
.classed("valgroup", true)
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = valgroup.selectAll("rect")
.data(function(d){return d;})
.enter().append("svg:rect")
.transition(t)
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
// column
rect.selectAll("rect")
.transition() // this is to create animations
.duration(500) // 500 millisecond
.ease("bounce")
.delay(500)
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
};
render(matrix);
setInterval( function() { render([[1, rand_it(10), rand_it(50)]]); console.log("2"); }, 5000 );
</script>
</body>
</html>
You are not using the transition() correctly. A transition changes from a previous value to a final value. So, in this code:
var something = svg.append("something").attr("x", 10);
something.transition().duration(500).attr("x", 20);
The x attribute of something will change from 10 to 20 in 500ms.
But when you do, as you did:
var rect = valgroup.selectAll("rect")
.data(function(d){return d;})
.enter().append("svg:rect")
.transition(t)
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
Where are the previous values? This is an "enter" selection. To make things more complicated, you did:
svg.selectAll("rect")
.transition(t)
.remove();
In the beginning of the function, so, there is no rectangle to make any transition.
I made a few changes in your code, removing the remove() and creating some "update" selections: https://jsfiddle.net/gerardofurtado/3ahrabyj/
Please have in mind that this is not an optimised code, even less a beautiful code: I made just the bare minimum changes to make the transitions to work, you'll have to make a lot of improvements here.