Skip to content

Commit ecde299

Browse files
committedMar 1, 2012
first commit
1 parent 26c8bda commit ecde299

9 files changed

+8609
-0
lines changed
 

‎choropleth.css

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
svg {
2+
background: #eee;
3+
width: 960px;
4+
height: 500px;
5+
}
6+
7+
text.title {
8+
font: 300 18px Helvetica Neue;
9+
fill: #222;
10+
}
11+
12+
#counties path {
13+
stroke: #fff;
14+
stroke-width: .25px;
15+
}
16+
17+
#states path {
18+
fill: none;
19+
stroke: #fff;
20+
stroke-width: 1.5px;
21+
}

‎choropleth.js

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
var data; // loaded asynchronously
2+
var data_quantile; // computed after load
3+
var data_mean;
4+
var data_std;
5+
var data_min;
6+
var data_max;
7+
8+
var county_codes;
9+
var m = Number.MAX_VALUE;
10+
var km_to_m = 1.0 / 1.609344;
11+
// removed 0 here and hacked the legend code so that we don't have white + white borders
12+
var legend_min = {1:m, 2:m, 3:m, 4:m, 5:m, 6:m, 7:m, 8:m};
13+
var legend_max = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0};
14+
/*
15+
0.00 - 0.04%
16+
0.04 - 0.09%
17+
0.09 - 0.13%
18+
0.13 - 0.18%
19+
0.18 - 0.24%
20+
0.24 - 0.32%
21+
0.32 - 0.46%
22+
0.46 - 21.51%
23+
*/
24+
var legend_min = {1:0.0000, 2:0.0004, 3:0.0009, 4:0.0013, 5:0.0018, 6:0.0024, 7:0.0032, 8:0.0046};
25+
var legend_max = {1:0.0004, 2:0.0009, 3:0.0013, 4:0.0018, 5:0.0024, 6:0.0032, 7:0.0046, 8:0.2151};
26+
27+
28+
var percent = d3.format(".2%");
29+
var percentx = function(x) { return d3.format(".2f")(100*x);}
30+
var fixed = d3.format(".0f");
31+
var number = d3.format("n");
32+
var fixedx = function(x) { return d3.format(".0f")(km_to_m*x);}
33+
var format = percent;
34+
var formatx = percentx;
35+
36+
var path = d3.geo.path();
37+
38+
var svg = d3.select("#chart")
39+
.append("svg:svg");
40+
41+
var title = svg.append("svg:text")
42+
.attr("text-anchor", "start")
43+
.attr("dx", 10)
44+
.attr("dy", 18)
45+
.attr("class", "title")
46+
;
47+
48+
var counties = svg.append("svg:g")
49+
.attr("id", "counties")
50+
.attr("class", "Reds");
51+
52+
var states = svg.append("svg:g")
53+
.attr("id", "states");
54+
55+
var legend = svg.append("svg:g")
56+
.attr("id", "legend")
57+
.attr("class", "Reds");
58+
59+
d3.json("us-counties.json", function(json) {
60+
counties.selectAll("path")
61+
.data(json.features)
62+
.enter().append("svg:path")
63+
.attr("class", data ? quantize : null)
64+
.attr("d", path)
65+
.on("mouseover", show(true))
66+
.on("mouseout", show(false))
67+
;
68+
69+
make_legend();
70+
});
71+
72+
d3.json("us-states.json", function(json) {
73+
states.selectAll("path")
74+
.data(json.features)
75+
.enter().append("svg:path")
76+
.attr("d", path);
77+
});
78+
79+
d3.json("county_codes.json", function(json) {
80+
county_codes = json;
81+
});
82+
83+
d3.json("data.json", function(json) {
84+
data = json;
85+
86+
populate_stats(data);
87+
88+
counties.selectAll("path")
89+
.attr("class", quantize)
90+
;
91+
92+
make_legend();
93+
94+
});
95+
96+
function make_legend()
97+
{
98+
if (!data)
99+
return;
100+
101+
// populate legend
102+
var mins = get_values(legend_min);
103+
legend.selectAll("path")
104+
.data(mins)
105+
.enter().append("svg:rect")
106+
.attr("width", 40)
107+
.attr("height", 20)
108+
.attr("y", function(d, i){ return 30 + i*21;})
109+
.attr("x", 10)
110+
.attr("class", function(d, i){return "q" + (i+1) + "-9";})
111+
;
112+
113+
var maxes = get_values(legend_max);
114+
legend.selectAll("text")
115+
.data(mins)
116+
.enter().append("svg:text")
117+
.attr("text-anchor", "start") // text-align
118+
.attr("x", 50)
119+
.attr("y", function(d, i){return 30 + i*21})
120+
.attr("dx", 3) // padding-right
121+
.attr("dy", 12 + 4) // vertical-align: used font size (copied from css. must be a better way)
122+
.attr("class", "legend")
123+
.text(function (d, i){return formatx(d) + " - " + format(maxes[i]);})
124+
;
125+
}
126+
127+
function show(b)
128+
{
129+
return function(d, i) {
130+
var s = counties.selectAll("path").filter(function(g){return g.id == d.id;});
131+
if (b)
132+
{
133+
title.text(county_codes[d.id] + ": " + format(data[d.id] !== undefined ? data[d.id] : 0));
134+
s.attr("class", "highlight");//"q0-9"
135+
}
136+
else
137+
{
138+
title.text("");
139+
s.attr("class", quantize);
140+
}
141+
}
142+
}
143+
144+
function __quantize(f, min, max)
145+
{
146+
// quantile scaling
147+
var q = data_quantile(f);
148+
149+
// log scaling (works for county_pop data)
150+
var l = ~~(Math.log(f+1) * (9 / (Math.log(data_max) - Math.log(data_min+1))));
151+
152+
// original scaling (ish).
153+
var o = ~~(f * 9 / (data_mean + data_std));
154+
155+
// original with less head room
156+
var ol = ~~(f * 11 / (data_mean + data_std));
157+
158+
// original with more head room
159+
var om = ~~(f * 7 / (data_mean + data_std));
160+
161+
return Math.max(min, Math.min(max, q));
162+
}
163+
164+
function quantize(d) {
165+
// map data[d.id] to be between 0 and 8
166+
// original code did:
167+
// values ranged between 1.2 and 30.1. Avg was 9, std is 3.65
168+
var min = 1;
169+
var max = 8;
170+
var f = data[d.id];
171+
if (f == undefined)
172+
f = 0;
173+
174+
var q = __quantize(f, min, max);
175+
legend_min[q] = Math.min(legend_min[q], f);
176+
legend_max[q] = Math.max(legend_max[q], f);
177+
178+
return "q" + q + "-9";
179+
}
180+
181+
var get_values = function(obj)
182+
{
183+
var values = [];
184+
for (var key in obj)
185+
{
186+
if (obj.hasOwnProperty(key))
187+
values.push(obj[key]);
188+
}
189+
return values;
190+
}
191+
192+
var populate_stats = function(data)
193+
{
194+
// need sorted values for quantile
195+
var values = get_values(data);
196+
data_quantile = d3.scale.quantile();
197+
data_quantile.domain(values);
198+
data_quantile.range([1,2,3,4,5,6,7,8]);
199+
200+
data_mean = d3.mean(values);
201+
data_std = std(values);
202+
data_max = d3.max(values);
203+
data_min = d3.min(values);
204+
}
205+
206+
var std = function(l)
207+
{
208+
var M = 0.0;
209+
var S = 0.0;
210+
var k = 1;
211+
for (var i = 0; i < l.length; i++)
212+
{
213+
var value = l[i];
214+
var tmpM = M;
215+
M += (value - tmpM) / k;
216+
S += (value - tmpM) * (value - M);
217+
k++;
218+
}
219+
return Math.sqrt(S / (k-1));
220+
}

‎county_codes.json

+1
Large diffs are not rendered by default.

‎county_pop2010.json

+1
Large diffs are not rendered by default.

‎d3.geo.js

+931
Large diffs are not rendered by default.

‎d3.js

+4,150
Large diffs are not rendered by default.

‎index.html

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
5+
<title>County Data</title>
6+
<script type="text/javascript" src="d3.js"></script>
7+
<script type="text/javascript" src="d3.geo.js"></script>
8+
<link type="text/css" rel="stylesheet" href="choropleth.css"/>
9+
<link type="text/css" rel="stylesheet" href="colorbrewer.css"/>
10+
</head>
11+
<body>
12+
<div id="chart"></div>
13+
<script type="text/javascript" src="choropleth.js"></script>
14+
</body>
15+
</html>

‎us-counties.json

+3,216
Large diffs are not rendered by default.

‎us-states.json

+54
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.