Created
November 5, 2015 18:50
-
-
Save iblind/6c75592f5053a86c5480 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
city | number_of_posts | population_ranking | state | estimate_2014 | actual_2010 | post_rank | lat | lon | posts_per_10k | ratio_rank | city_shrt | rPop | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Dallas | 1581 | 9 | Texas | 1,281,047 | 1,197,816 | 3 | 32.769582 | -96.791764 | 12.34146757 | 1 | DAL | 0.2191423 | |
Phoenix | 1356 | 6 | Arizona | 1,537,058 | 1,445,632 | 4 | 33.462898 | -112.076986 | 8.822048355 | 2 | PHX | 0.2400428 | |
San Diego | 1168 | 8 | California | 1,381,069 | 1,307,402 | 5 | 32.745467 | -117.154215 | 8.457216837 | 3 | SDG | 0.2275366 | |
Chicago | 1938 | 3 | Illinois | 2,722,389 | 2,695,598 | 2 | 41.864933 | -87.625039 | 7.118747541 | 4 | CHI | 0.3194616 | |
Philadelphia | 940 | 5 | Pennsylvania | 1,560,297 | 1,526,006 | 7 | 39.962926 | -75.159232 | 6.024494055 | 5 | PHIL | 0.2418507 | |
Houston | 1021 | 4 | Texas | 2,239,558 | 2,100,263 | 6 | 29.748644 | -95.362839 | 4.55893529 | 6 | HOU | 0.2897509 | |
San Antonio | 624 | 7 | Texas | 1,436,697 | 1,327,407 | 9 | 29.409079 | -98.489685 | 4.343295768 | 7 | SAN | 0.2320739 | |
New York | 2669 | 1 | New York | 8,491,079 | 8,175,133 | 1 | 40.71455 | -74.007124 | 3.143298985 | 8 | NYC | 0.5641896 | |
Los Angeles | 718 | 2 | California | 3,928,864 | 3,792,621 | 8 | 34.037002 | -118.234578 | 1.827500265 | 9 | LA | 0.3837754 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title> All the missed connections, where do they all come from?</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<style> | |
body { | |
font-family:Arial, Helvetica, sans-serif; | |
} | |
.axisGeo path, | |
.axisGeo line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axisGeo text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
#allTooltips { | |
position: relative; | |
} | |
#tooltip_3, #tooltip_1 { | |
position: absolute; | |
top:-15px; | |
right:45%; | |
width: 270px; | |
height: 80px; | |
padding: 5px; | |
background-color: white; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
-webkit-box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
-moz-box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
pointer-events: none; | |
z-index: 10; | |
opacity: 0.9; | |
} | |
#tooltip_3.hidden, #tooltip_1.hidden { | |
display: none; | |
} | |
#tooltip_3, #tooltip_1 { | |
margin: 0; | |
font-family: Arial, Helvetica, sans-serif; | |
font-size: 16px; | |
line-height: 14px; | |
} | |
.cityshort .cityshort2 { | |
font-size: 13px, | |
fill: MidnightBlue, | |
font-family: Arial | |
} | |
#tooltip_2 { | |
position: absolute; | |
top:-15px; | |
right:45%; | |
width: 270px; | |
height: 80px; | |
padding:8px; | |
background-color: white; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
-webkit-box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
-moz-box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
box-shadow: 4px 4px 10px rgba(0,0,0,0.4); | |
pointer-events: none; | |
z-index: 10; | |
opacity: 1; | |
} | |
#tooltip_2.hidden { | |
display: none; | |
} | |
#tooltip_2 { | |
margin: 0; | |
font-family: Arial, Helvetica, sans-serif; | |
font-size: 16px; | |
line-height: 14px; | |
} | |
.legendGeo circle { | |
fill: none; | |
stroke: #ccc; | |
} | |
span#city, span#city2 { | |
font-size: 24px; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Adding divs for buttons above graph and mouseover tooltips --> | |
<div id="buttonsGeo"> | |
<div id="popGeo">Population</div> | |
<div id="postsGeo">Posts</div> | |
<div id="plotGeo">Posts/population</div> | |
</div> | |
<div id="allTooltips"> | |
<div id ="tooltip_1" class="hidden"> | |
<p><center><strong><span id="city"></span></strong></center></p> | |
<p><center>Population: <span id="popvalue"></span><center></p> | |
</div> | |
<div id ="tooltip_2" class="hidden"> | |
<p><center><strong><span id="city2"></span></strong></center></p> | |
<p><center><span id="value2"></span> missed connections for 10,000 residents</p></center> | |
</div> | |
<div id ="tooltip_3" class="hidden"> | |
<p><center><strong><span id="city"></span></strong></center></p> | |
<p><center>Missed connections: <span id="valueGeo"></span></center></p> | |
</div> | |
</div> | |
<br> | |
<!-- svg --> | |
<div id="mapGeo"> | |
</div> | |
<script type="text/javascript"> | |
//Adding global variables | |
var paddingGeo = {top: 10, left: 10, bottom: 10, right: 10}, | |
wGeo = parseInt(d3.select('#mapGeo').style('width')), | |
wGeo = wGeo - paddingGeo.left - paddingGeo.right, | |
mapRatio = .5, | |
hGeo = wGeo * mapRatio, | |
projection = d3.geo.albersUsa().scale(wGeo).translate([wGeo/2, hGeo/2]); | |
path = d3.geo.path().projection(projection); | |
//Loading the map, + its relevant JSON | |
d3.json("us-states.json", function(json){ | |
function resize(){ | |
wGeo = parseInt(d3.select('#mapGeo').style('width')); | |
wGeo = wGeo - paddingGeo.left - paddingGeo.right; | |
hGeo = wGeo * mapRatio; | |
projection.translate([wGeo/2, hGeo/2]).scale(wGeo); | |
svgGeo.selectAll("path") | |
.attr("d", path); | |
} | |
var svgGeo = d3.select('#mapGeo').append('svg') | |
.style('height', hGeo+ 'px') | |
.style('width', wGeo +'px') | |
d3.select(window).on('resize', resize); | |
svgGeo.selectAll("path") | |
.data(json.features) | |
.enter() | |
.append("path") | |
.attr({ | |
"d": path, | |
"fill": "#B0B0B0", | |
"stroke": "white", | |
"stroke-width": 0.3, | |
"opacity": 1, | |
class: "map" | |
}); | |
d3.csv("cities_pop.csv", function(data){ | |
//Setting scale for circle radius | |
var rScaleGeo = d3.scale.linear() | |
.domain([0, d3.max(data, function(d){ | |
return Math.sqrt(d.estimate_2014.replace(/\,/g,''));})]) | |
.range([1,15]); | |
//Adding first set of circles, to be used as bottom row of scatter plot | |
svgGeo.selectAll("circle.secondary") | |
.data(data) | |
.enter() | |
.append("circle") | |
.attr({ | |
class:"secondary", | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": 1 | |
}) | |
.style({ | |
"fill": "#43a2ca", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
}) | |
//Adding circles to the map | |
svgGeo.selectAll("circle.regular") | |
.data(data) | |
.enter() | |
.append("circle") | |
.attr({ | |
class:"regular", | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": function(d){return rScaleGeo(Math.sqrt(d.estimate_2014.replace(/\,/g,'')));} | |
}) | |
.style({ | |
"fill": "#43a2ca", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
}) | |
.transition() | |
.duration(500) | |
.ease("circle") | |
.style("opacity", 1); | |
//Adding tooltip mousover + mouseout functionality | |
svgGeo.selectAll("circle").on("mouseover", function(d) { | |
//Update the tooltip value | |
d3.select("#tooltip_1") | |
.select("#popvalue") | |
.text(d.estimate_2014); | |
d3.select("#tooltip_1") | |
.select("#city") | |
.text(d.city); | |
//Show the tooltip | |
d3.select("#tooltip_1") | |
.classed("hidden", false); | |
}) | |
.on("mouseout", function() { | |
//Hide the tooltip | |
d3.select("#tooltip_1").classed("hidden", true) | |
}); | |
//ADDING "POPULATION" BUTTON FUNCTIONALITY | |
d3.select("#popGeo") | |
.on("click", function(){ | |
//Removing x + y labels from scatterplot; removing legends(circle+text) | |
d3.selectAll("text.xlabelGeo").remove(); | |
d3.selectAll("circle.legendGeo").remove(); | |
d3.selectAll("text.legendGeo").remove(); | |
d3.selectAll("g").remove(); | |
//Reconfiguring rScale | |
var rScaleGeo = d3.scale.linear() | |
.domain([0, d3.max(data, function(d){ | |
return parseFloat(d.estimate_2014); | |
})]) | |
.range([5,15]); | |
//Restoring map's opacity to it appears in foreground | |
d3.selectAll("path.map") | |
.transition() | |
.delay(10) | |
.duration(700) | |
.attr({ | |
"stroke-width": 0.5, | |
"opacity": 1 | |
}); | |
//Removing the top and bottom text labels added during scatterplot step | |
d3.selectAll("text.cityshort") | |
.remove(); | |
d3.selectAll("text.cityshort2") | |
.remove(); | |
//Moving bottom row of circles back to initial positions, below regular circles | |
d3.selectAll("circle.secondary") | |
.transition() | |
.attr({ | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": 1 | |
}) | |
.style({ | |
"fill": "#43a2ca", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
}) | |
//Moving top row of circles back to their rightful place, as is their birthright | |
d3.selectAll("circle.regular") | |
.transition() | |
.duration(500) | |
.attr({ | |
class:"regular", | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": function(d){return rScaleGeo(parseFloat(d.estimate_2014));} | |
}) | |
.style({ | |
"fill": "#43a2ca", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
"opacity": 1 | |
}); | |
//Re-adding tooltip mousover + mouseout functionality | |
svgGeo.selectAll("circle").on("mouseover", function(d) { | |
//Update the tooltip position and value | |
d3.select("#tooltip_1") | |
.select("#popvalue") | |
.text(d.estimate_2014); | |
d3.select("#tooltip_1") | |
.select("#city") | |
.text(d.city); | |
//Show the tooltip | |
d3.select("#tooltip_1") | |
.classed("hidden", false); | |
}) | |
.on("mouseout", function() { | |
//Hide the tooltip | |
d3.select("#tooltip_1").classed("hidden", true) | |
}); | |
});//End of "posts" button | |
//ADDING "POSTS" BUTTON FUNCTIONALITY | |
d3.select("#postsGeo") | |
.on("click", function(){ | |
//Removing x + y labels from scatterplot; removing legends(circle+text) | |
d3.selectAll("text.xlabelGeo").remove(); | |
d3.selectAll("circle.legendGeo").remove(); | |
d3.selectAll("text.legendGeo").remove(); | |
d3.selectAll("g").remove(); | |
//Reconfiguring rScale | |
var rScaleGeo = d3.scale.linear() | |
.domain([0, d3.max(data, function(d){ | |
return parseFloat(d.number_of_posts); | |
})]) | |
.range([5,15]); | |
//Restoring map's opacity to it appears in foreground | |
d3.selectAll("path.map") | |
.transition() | |
.delay(10) | |
.duration(700) | |
.attr({ | |
"stroke-width": 0.5, | |
"opacity": 1 | |
}); | |
//Removing the top and bottom text labels added during scatterplot step | |
d3.selectAll("text.cityshort") | |
.remove(); | |
d3.selectAll("text.cityshort2") | |
.remove(); | |
//Moving bottom row of circles back to initial positions, below regular circles | |
d3.selectAll("circle.secondary") | |
.transition() | |
.attr({ | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": 1 | |
}) | |
.style({ | |
"fill": "#43a2ca", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
}) | |
//Moving top row of circles back to their rightful place, as is their birthright | |
d3.selectAll("circle.regular") | |
.transition() | |
.duration(500) | |
.attr({ | |
class:"regular", | |
"cx": function(d){return projection([d.lon, d.lat])[0];}, | |
"cy": function(d){return projection([d.lon, d.lat])[1];}, | |
"r": function(d){return rScaleGeo(parseFloat(d.number_of_posts));} | |
}) | |
.style({ | |
"fill": "#FF1493", | |
"opacity": 0, | |
"stroke-width":0.7, | |
"stroke":"white", | |
"opacity":1 | |
}); | |
//Re-adding tooltip mousover + mouseout functionality | |
svgGeo.selectAll("circle").on("mouseover", function(d) { | |
//Update the tooltip position and value | |
d3.select("#tooltip_3") | |
.select("#valueGeo") | |
.text(d.number_of_posts); | |
d3.select("#tooltip_3") | |
.select("#city") | |
.text(d.city); | |
//Show the tooltip | |
d3.select("#tooltip_3") | |
.classed("hidden", false); | |
}) | |
.on("mouseout", function() { | |
//Hide the tooltip | |
d3.select("#tooltip_3").classed("hidden", true) | |
}); | |
});//End of "posts" button | |
d3.select("#plotGeo").on("click", function(){ | |
//GENERAL PREPPING FOR SCATTERPLOT TRANSITION: | |
//Fade the map of the U.S. | |
d3.selectAll("path.map") | |
.transition() | |
.delay(10) | |
.duration(1000) | |
.attr({ | |
"stroke-width": 0, | |
"opacity": 0 | |
}); | |
//Remove older elements in case user clicks twice | |
d3.selectAll("text.xlabelGeo").remove(); | |
d3.selectAll("circle.legendGeo").remove(); | |
d3.selectAll("text.legendGeo").remove(); | |
d3.selectAll("g").remove(); | |
//Adding scales for: | |
//radius, when scaled for POPULATION of each city | |
//radius, when scaled for POSTS in each city | |
//xAxis, to show the order of rankings | |
//NOTE::: no need for yAxis, since this stays fixed | |
var xScaleGeo = d3.scale | |
.linear() | |
.domain([1, d3.max(data, function(d){ return +d.ratio_rank;})]) | |
.rangeRound([0+paddingGeo, wGeo-paddingGeo]); | |
var rScalePostsGeo = d3.scale | |
.linear() | |
.domain([0, d3.max(data, function(d){ return d.number_of_posts;})]) | |
.rangeRound([2,15]); | |
var rScalePopGeo = d3.scale | |
.linear() | |
.domain([0, d3.max(data, function(d){return parseFloat(d.estimate_2014);})]) | |
.rangeRound([5,20]); | |
var xAxisGeo = d3.svg.axis() | |
.scale(xScaleGeo) | |
.orient("top"); | |
var xAxis2Geo = d3.svg.axis() | |
.scale(xScaleGeo) | |
.orient("bottom"); | |
//BEGIN CHANGES TO SVG | |
//Moving top row of circles from map to ranked row | |
svgGeo.selectAll("circle.regular") | |
.transition() | |
.delay(10) | |
.duration(500) | |
.attr({ | |
cx: function(d){ return xScaleGeo(+d.ratio_rank);}, | |
cy: 150, | |
"r": function(d){ return rScalePostsGeo(d.number_of_posts);} | |
}) | |
.style({ | |
"fill": "white", | |
"stroke": "#FF1493", | |
"stroke-width": 2 | |
}); | |
//Moving bottom row of circles from map to ranked row | |
svgGeo.selectAll("circle.secondary") | |
.transition() | |
.delay(10) | |
.duration(500) | |
.attr({ | |
cx: function(d){ return xScaleGeo(+d.ratio_rank);}, | |
cy: 315, | |
"r": function(d){ return rScalePopGeo(parseFloat(d.estimate_2014));} | |
}) | |
.style({ | |
"fill": "white", | |
"stroke": "#43a2ca", | |
"stroke-width": 2, | |
"opacity": 1 | |
}); | |
//Adding text legends to the ranked scatterplot | |
svgGeo.selectAll("text.cityshort") | |
.data(data) | |
.enter() | |
.append("text") | |
.text(function(d){ return d.city_shrt;}) | |
.attr("opacity", 0) | |
.transition() | |
.delay(500) | |
.attr({ | |
class:"cityshort", | |
x: function(d,i){return xScaleGeo(+d.ratio_rank)-12;}, | |
y: 100, | |
"opacity": 1, | |
"font-size": "13px", | |
"fill": "MidnightBlue", | |
"font-family": "arial" | |
}); | |
svgGeo.selectAll("text.cityshort2") | |
.data(data) | |
.enter() | |
.append("text") | |
.text(function(d){ return d.city_shrt;}) | |
.attr("opacity", 0) | |
.transition() | |
.delay(500) | |
.attr({ | |
class:"cityshort2", | |
x: function(d,i){return xScaleGeo(+d.ratio_rank)-12;}, | |
y: 370, | |
"opacity": 1, | |
"font-size": "13px", | |
"fill": "MidnightBlue", | |
"font-family": "arial" | |
}); | |
//Add circle size legends | |
svgGeo.append("circle") | |
.attr({ | |
class: "legendGeo", | |
cx: 45, | |
cy: (hGeo/2)-210, | |
"r": 15, | |
}) | |
.style({ | |
"fill": "White", | |
"stroke": "#FF1493", | |
"stroke-width": 2, | |
"opacity": 0 | |
}) | |
.transition() | |
.duration(500) | |
.style("opacity", 1); | |
svgGeo.append("circle") | |
.attr({ | |
class: "legendGeo", | |
cx: 45, | |
cy: (hGeo/2)+200, | |
"r": 15, | |
}) | |
.style({ | |
fill: "White", | |
stroke: "#43a2ca", | |
"stroke-width": 2, | |
"opacity": 0 | |
}) | |
.transition() | |
.duration(500) | |
.style("opacity", 1); | |
//Legend circle text | |
svgGeo.append("text") | |
.attr({ | |
class: "legendGeo", | |
x: 33, | |
y: 17, | |
"fill": "LightSlateGray", | |
"font-size": 10 | |
}) | |
.style("opacity", 0) | |
.text("Posts") | |
.transition() | |
.delay(500) | |
.style("opacity", 1); | |
svgGeo.append("text") | |
.attr({ | |
class: "legendGeo", | |
x: 22, | |
y: 479, | |
"fill": "LightSlateGray", | |
"font-size": 10 | |
}) | |
.text("Population") | |
.style("opacity", 0) | |
.transition() | |
.delay(500) | |
.style("opacity", 1); | |
//Adding text labels to x Axes | |
svgGeo.append("text") | |
.transition() | |
.delay(500) | |
.attr("class", "xlabelGeo") | |
.attr("text-anchor", "end") | |
.attr("x", wGeo-115) | |
.attr("y", hGeo/2) | |
.text("Rank by number of missed connections for every 10,000 inhabitants"); | |
//Adding x Axes | |
svgGeo.append("g") | |
.attr("class", "axisGeo") | |
.attr("transform", "translate(0,"+ 220+")") | |
.call(xAxisGeo); | |
svgGeo.append("g") | |
.attr("class", "axisGeo") | |
.attr("transform", "translate(0,"+ 270+")") | |
.call(xAxis2Geo); | |
//Adding mouseover | |
svgGeo.selectAll("circle").on("mouseover", function(d) { | |
//Update the tooltip position and value | |
d3.select("#tooltip_2") | |
.select("#value2") | |
.text(d.posts_per_10k.toString().substr(0,4)); | |
d3.select("#tooltip_2") | |
.select("#city2") | |
.text(d.city); | |
//Show the tooltip | |
d3.select("#tooltip_2").classed("hidden", false); | |
}) | |
.on("mouseout", function() { | |
//Hide the tooltip | |
d3.select("#tooltip_2").classed("hidden", true) | |
}); | |
});//End of plotting | |
}); //End of CSV load | |
}); //End of JSON load | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment