Skip to content

Instantly share code, notes, and snippets.

@dnprock
Last active July 10, 2018 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dnprock/1de12e0050bbf14c458f to your computer and use it in GitHub Desktop.
Save dnprock/1de12e0050bbf14c458f to your computer and use it in GitHub Desktop.
US States Map - Choropleth plus Bar
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
height: 500px;
position: relative;
}
/* stylesheet for your custom graph */
.categories {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
.categories-choropleth {
fill: #ccc;
}
#tooltip-container {
position: absolute;
background-color: #fff;
color: #000;
padding: 10px;
border: 1px solid;
display: none;
}
#canvas svg {
border: 0px;
}
.tooltip_key {
font-weight: bold;
}
.tooltip_value {
margin-left: 20px;
float: right;
}
.x-axis {
fill: #000;
}
.chart {
background: #fff;
margin: 5px;
}
.chart .category-bar {
stroke: white;
fill: steelblue;
}
.chart .score {
fill: white;
}
.chart text.name {
fill: #000;
}
.chart line {
stroke: #c1c1c1;
}
.chart .rule {
fill: #000;
}
.main-category-text {
fill: #FF4A4A;
}
.main-category-bar {
stroke: #FF4A4A;
stroke-width: 2px;
}
</style>
<div id="tooltip-container"></div>
<div id="canvas-svg"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.1.0/topojson.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
d3.csv("population.csv", function(err, data) {
var config = {"color1":"#c3e2ff","color2":"#08306B","mainCategory":"Washington","averageCategory":"Nation Average","stateDataColumn":"state_and_district_of_columbia","valueDataColumn":"obese_adults_number"}
var WIDTH = 800, HEIGHT = 400;
var COLOR_COUNTS = 9;
var SCALE = 0.7;
var MAIN_CATEGORY = config.mainCategory;
var AVG_CATEGORY = config.averageCategory;
function Interpolate(start, end, steps, count) {
var s = start,
e = end,
final = s + (((e - s) / steps) * count);
return Math.floor(final);
}
function Color(_r, _g, _b) {
var r, g, b;
var setColors = function(_r, _g, _b) {
r = _r;
g = _g;
b = _b;
};
setColors(_r, _g, _b);
this.getColors = function() {
var colors = {
r: r,
g: g,
b: b
};
return colors;
};
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
var COLOR_FIRST = config.color1, COLOR_LAST = config.color2;
var rgb = hexToRgb(COLOR_FIRST);
var COLOR_START = new Color(rgb.r, rgb.g, rgb.b);
rgb = hexToRgb(COLOR_LAST);
var COLOR_END = new Color(rgb.r, rgb.g, rgb.b);
var MAP_CATEGORY = config.stateDataColumn;
var MAP_VALUE = config.valueDataColumn;
var width = WIDTH,
height = HEIGHT;
var valueById = d3.map();
var startColors = COLOR_START.getColors(),
endColors = COLOR_END.getColors();
var colors = [];
for (var i = 0; i < COLOR_COUNTS; i++) {
var r = Interpolate(startColors.r, endColors.r, COLOR_COUNTS, i);
var g = Interpolate(startColors.g, endColors.g, COLOR_COUNTS, i);
var b = Interpolate(startColors.b, endColors.b, COLOR_COUNTS, i);
colors.push(new Color(r, g, b));
}
var quantize = d3.scale.quantize()
.domain([0, 1.0])
.range(d3.range(COLOR_COUNTS).map(function(i) { return i }));
var path = d3.geo.path();
var svg = d3.select("#canvas-svg").append("svg")
.attr("width", width)
.attr("height", height);
d3.tsv("https://s3-us-west-2.amazonaws.com/vida-public/geo/us-state-names.tsv", function(error, names) {
name_id_map = {};
id_name_map = {};
for (var i = 0; i < names.length; i++) {
name_id_map[names[i].name] = names[i].id;
id_name_map[names[i].id] = names[i].name;
}
data.forEach(function(d) {
var id = name_id_map[d[MAP_CATEGORY]];
valueById.set(id, +d[MAP_VALUE]);
});
quantize.domain([d3.min(data, function(d){ return +d[MAP_VALUE] }),
d3.max(data, function(d){ return +d[MAP_VALUE] })]);
function makeBars() {
var names = [],
ids = [],
name_values = [],
values = [],
chart,
width = 400,
bar_height = 20,
height = (bar_height + 2 * gap) * names.length;
var total_categories = 0, categories_count = 0;
Object.keys(name_id_map).forEach(function(n) {
if (valueById.get(+name_id_map[n])) {
ids.push(+name_id_map[n]);
values.push(valueById.get(+name_id_map[n]));
name_values.push({name: n, value: valueById.get(+name_id_map[n])});
total_categories += valueById.get(+name_id_map[n]);
categories_count++;
}
});
values.push(Math.round(total_categories / categories_count));
name_values.push({name: AVG_CATEGORY, value: Math.round(total_categories / categories_count)});
values = values.sort(function(a, b) {
return -(a - b);
});
name_values = name_values.sort(function(a, b) {
return -(a.value - b.value);
});
name_values.forEach(function(d) {
names.push(d.name);
});
var left_width = 150;
var x = d3.scale.linear()
.domain([0, d3.max(values)])
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var gap = 2;
// redefine y for adjusting the gap
var y = d3.scale.ordinal()
.domain(names)
.rangeBands([0, (bar_height + 2 * gap) * names.length]);
chart = d3.select("#canvas-svg")
.append('svg')
.attr('class', 'chart')
.attr('width', left_width + width + 100)
.attr('height', (bar_height + gap * 2) * names.length + 30)
.append("g")
.attr("transform", "translate(10, 20)");
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + left_width + ", 0)")
.call(xAxis)
.append("text")
.attr("transform", "rotate(90) translate(10, " + (-width - 20) + ")")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "right")
.text(MAP_VALUE);
chart.selectAll(".tick").append("line")
.attr("x1", 0)
.attr("x2", 0)
.attr("y1", 0)
.attr("y2", (bar_height + gap * 2) * names.length);
chart.selectAll("rect")
.data(name_values)
.enter().append("rect")
.attr("x", left_width)
.attr("y", function(d) { return y(d.name) + gap; })
.attr("name", function(d, i) {
return d.name;
})
.attr("width", function(d, i) {
return x(d.value);
})
.attr("height", bar_height)
.style("fill", function(d) {
var i = quantize(d.value);
var color = colors[i].getColors();
return "rgb(" + color.r + "," + color.g +
"," + color.b + ")";
})
.attr("class", function(d) {
if (d.name === MAIN_CATEGORY || d.name === AVG_CATEGORY) {
return "main-category-bar";
} else {
return "category-bar";
}
});
chart.selectAll("text.score")
.data(name_values)
.enter().append("text")
.attr("x", function(d) { return x(d.value) + left_width; })
.attr("y", function(d, i){ return y(d.name) + y.rangeBand()/2; } )
.attr("dx", -5)
.attr("dy", ".36em")
.attr("text-anchor", "end")
.attr('class', 'score')
.text(function(d) {
return d.value;
});
chart.selectAll("text.name")
.data(name_values)
.enter().append("text")
.attr("x", left_width / 2)
.attr("y", function(d, i){
return y(d.name) + y.rangeBand()/2; } )
.attr("dy", ".36em")
.attr("text-anchor", "middle")
.attr('class', function(d) {
if (d.name === MAIN_CATEGORY || d.name === AVG_CATEGORY) {
return "main-category-text";
} else {
return "";
}
})
.text(function(d) {
return d.name;
});
}
function makeMap(us) {
svg.append("g")
.attr("class", "categories-choropleth")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("transform", "scale(" + SCALE + ")")
.style("fill", function(d) {
if (valueById.get(d.id)) {
var i = quantize(valueById.get(d.id));
var color = colors[i].getColors();
return "rgb(" + color.r + "," + color.g +
"," + color.b + ")";
} else {
return "";
}
})
.attr("d", path)
.on("mousemove", function(d) {
var html = "";
html += "<div class=\"tooltip_kv\">";
html += "<span class=\"tooltip_key\">";
html += id_name_map[d.id];
html += "</span>";
html += "<span class=\"tooltip_value\">";
html += (valueById.get(d.id) ? valueById.get(d.id) : "");
html += "";
html += "</span>";
html += "</div>";
$("#tooltip-container").html(html);
$(this).attr("fill-opacity", "0.8");
$("#tooltip-container").show();
var coordinates = d3.mouse(this);
var map_width = $('.categories-choropleth')[0].getBoundingClientRect().width;
if (d3.event.pageX < map_width / 2) {
d3.select("#tooltip-container")
.style("top", (d3.event.pageY + 15) + "px")
.style("left", (d3.event.pageX + 15) + "px");
} else {
var tooltip_width = $("#tooltip-container").width();
d3.select("#tooltip-container")
.style("top", (d3.event.pageY + 15) + "px")
.style("left", (d3.event.pageX - tooltip_width - 30) + "px");
}
})
.on("mouseout", function() {
$(this).attr("fill-opacity", "1.0");
$("#tooltip-container").hide();
});
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "categories")
.attr("transform", "scale(" + SCALE + ")")
.attr("d", path);
}
d3.json("https://s3-us-west-2.amazonaws.com/vida-public/geo/us.json", function(error, us) {
makeMap(us);
makeBars(data);
});
});
});
</script>
state_and_district_of_columbia obese_adults_number obese_adults overweight_incl_obese_adults_number overweight_incl_obese_adults obese_children_and_adolescents_number obese_children_and_adolescents obesity_rank_number
Alabama 30.1 30.10% 65.4 65.40% 16.7 16.70% 3
Alaska 27.3 27.30% 64.5 64.50% 11.1 11.10% 14
Arizona 23.3 23.30% 59.5 59.50% 12.2 12.20% 40
Arkansas 28.1 28.10% 64.7 64.70% 16.4 16.40% 9
California 23.1 23.10% 59.4 59.40% 13.2 13.20% 41
Colorado 21 21.00% 55 55.00% 9.9 9.90% 51
Connecticut 20.8 20.80% 58.7 58.70% 12.3 12.30% 49
District of Columbia 22.1 22.10% 55 55.00% 14.8 14.80% 43
Delaware 25.9 25.90% 63.9 63.90% 22.8 22.80% 22
Florida 23.3 23.30% 60.8 60.80% 14.4 14.40% 39
Georgia 27.5 27.50% 63.3 63.30% 16.4 16.40% 12
Hawaii 20.7 20.70% 55.3 55.30% 13.3 13.30% 50
Idaho 24.6 24.60% 61.4 61.40% 10.1 10.10% 31
Illinois 25.3 25.30% 61.8 61.80% 15.8 15.80% 26
Indiana 27.5 27.50% 62.8 62.80% 15.6 15.60% 11
Iowa 26.3 26.30% 63.4 63.40% 12.5 12.50% 19
Kansas 25.8 25.80% 62.3 62.30% 14 14.00% 23
Kentucky 28.4 28.40% 66.8 66.80% 20.6 20.60% 7
Louisiana 29.5 29.50% 64.2 64.20% 17.2 17.20% 4
Maine 23.7 23.70% 60.8 60.80% 12.7 12.70% 34
Maryland 25.2 25.20% 61.5 61.50% 13.3 13.30% 28
Massachusetts 20.9 20.90% 56.8 56.80% 13.6 13.60% 48
Michigan 27.7 27.70% 63.9 63.90% 14.5 14.50% 10
Minnesota 24.8 24.80% 61.9 61.90% 10.1 10.10% 30
Mississippi 34.4 34.40% 67.4 67.40% 17.8 17.80% 1
Missouri 27.4 27.40% 63.3 63.30% 15.6 15.60% 13
Montana 21.7 21.70% 59.6 59.60% 11.1 11.10% 45
Nebraska 26.5 26.50% 63.9 63.90% 11.9 11.90% 18
Nevada 23.6 23.60% 61.8 61.80% 12.4 12.40% 36
New Hampshire 23.6 23.60% 60.8 60.80% 12.9 12.90% 35
New Jersey 22.9 22.90% 60.5 60.50% 13.7 13.70% 42
New Mexico 23.3 23.30% 60.3 60.30% 16.8 16.80% 38
New York 23.5 23.50% 60 60.00% 15.3 15.30% 37
North Carolina 27.1 27.10% 63.4 63.40% 19.3 19.30% 16
North Dakota 25.9 25.90% 64.5 64.50% 12.1 12.10% 21
Ohio 26.9 26.90% 63.3 63.30% 14.2 14.20% 17
Oklahoma 28.1 28.10% 64.2 64.20% 15.4 15.40% 8
Oregon 25 25.00% 60.8 60.80% 14.1 14.10% 29
Pennsylvania 25.7 25.70% 61.9 61.90% 13.3 13.30% 24
Rhode Island 21.4 21.40% 60.4 60.40% 11.9 11.90% 46
South Carolina 29.2 29.20% 65.1 65.10% 18.9 18.90% 5
South Dakota 26.1 26.10% 64.2 64.20% 12.1 12.10% 20
Tennessee 29 29.00% 65 65.00% 20 20.00% 6
Texas 27.2 27.20% 64.1 64.10% 19.1 19.10% 15
Utah 21.8 21.80% 56.4 56.40% 8.5 8.50% 44
Vermont 21.1 21.10% 56.9 56.90% 11.3 11.30% 47
Virginia 25.2 25.20% 61.6 61.60% 13.8 13.80% 27
Washington 24.5 24.50% 60.7 60.70% 10.8 10.80% 32
West Virginia 30.6 30.60% 66.8 66.80% 20.9 20.90% 2
Wisconsin 25.5 25.50% 62.4 62.40% 13.5 13.50% 25
Wyoming 24 24.00% 61.7 61.70% 8.7 8.70% 33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment