Create a gist now

Instantly share code, notes, and snippets.

@Caged /.gitignore
Last active Aug 29, 2015

US Federal Judicial Districts
.DS_Store
node_modules
us-judicial-districts.zip
build
<!doctype html>
<meta charset="utf-8">
<style type="text/css" media="screen">
body {
margin: 0;
}
.district {
stroke: #fff;
stroke-width: 1;
fill-opacity: 0.6;
}
.district:hover {
fill-opacity: 0.8;
}
.county {
fill: none;
stroke: #333;
stroke-width: 0.5;
stroke-opacity: 0.6;
}
.label {
font-family: Helvetica;
font-size: 11px;
font-weight: bold;
fill-opacity: 1;
text-anchor: middle;
stroke: none;
pointer-events: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script type="text/javascript" charset="utf-8">
var width = 960,
height = 600
var path = d3.geo.path()
var color = d3.scale.category20()
var svg = d3.select("body").append('svg')
.attr('width', width)
.attr('height', height)
d3.json('us.json', function(error, us) {
if(error) return console.error("Boom goes the dynamite: " + error)
var dem = 0, rep = 0
us.objects.districts.geometries.forEach(function(d) {
d.properties.judges.forEach(function(j) {
if(j.ppa === 'Democratic') dem++
if(j.ppa === 'Republican') rep++
})
})
console.log(dem + " Democrat appointments", rep + " Republican appointments");
svg.append('path')
.datum(topojson.mesh(us, us.objects.counties))
.attr('class', 'county')
.attr('d', path)
districts = svg.selectAll('.district')
.data(topojson.feature(us, us.objects.districts).features)
.enter().append('path')
.attr('class', 'district')
.attr('d', path)
.style('fill', function(d, i) { return color(i) })
.on('click', function(district) {
var d = 0, r = 0
var names = district.properties.judges.map(function(j) {
if(j.ppa === 'Democratic') d++
if(j.ppa === 'Republican') r++
return j.ppa + ": " + j.name
}).join("\n")
console.log("D: " + d, "R: " + r, "\n\n" + names);
})
var labels = svg.append('g')
districts.each(function(d) {
var center = path.centroid(d)
labels.append('text')
.attr('class', 'label')
.attr('dx', function(d) { return center[0] })
.attr('dy', function(d) { return center[1] })
.text(d.properties.jdcode)
})
})
</script>
</body>
all: us.json
clean:
rm -rf -- us.json \
build/*-ungrouped.* \
build/*.json \
build/judicial-districts.shp \
build/judicial-districts.sbn \
build/judicial-districts.sbx \
build/judicial-districts.shx \
build/judicial-districts.prj \
build/judicial-districts.dbf
.PHONY: all clean
build/judicial-districts.shp:
rm -rf $(basename $@)
mkdir -p $(basename $@)
tar -xzm -C build -f ./build/judicial-districts.tar.gz
for file in $(basename $@)/*; do chmod 644 $$file; mv $$file $(basename $@).$${file##*.}; done
rmdir $(basename $@)
build/counties.json: build/judicial-districts.shp
node_modules/.bin/topojson \
-o $@ \
--no-pre-quantization \
--post-quantization=1e6 \
--simplify=7e-7 \
-p jdcode=+JDCODE,state=State,name=JD_NAME \
--id-property=+FIPS \
-- counties=build/judicial-districts.shp
build/districts.json: build/counties.json
rm $(basename $@)-unreconciled.json
node_modules/.bin/topojson-merge \
-o $(basename $@)-unreconciled.json \
--in-object=counties \
--out-object=districts \
--key='d.properties.jdcode' \
-- $<
./reconcile-judges < $(basename $@)-unreconciled.json > $@
us.json: build/districts.json
node_modules/.bin/topojson-merge \
-o $@ \
--in-object=districts \
--out-object=nation \
-- $<
{
"name": "anonymous",
"version": "0.0.1",
"private": true,
"dependencies": {
"fast-csv": "0.2.4",
"topojson": ">=1.6.2 <2"
}
}
#!/usr/bin/env node
// Because no one bothered to standardize on court names or give them an ID and
// assign judges to one, we're left with the cesspool you see below
//
var fs = require('fs'),
csv = require('fast-csv')
var topo = JSON.parse(fs.readFileSync('build/districts-unreconciled.json'))
var judges = [],
states = [],
names = [],
locations = ['Northern', 'Southern', 'Middle', 'Western', 'Eastern']
// Only keep active US District Court judges
function terminated(record) {
var termination = record['Date of Termination'],
death = record['Death year'],
courtType = record['Court Type'],
retired = record['Retirement from Active Service']
if(termination === '' && courtType === 'USDC' && retired === '') {
judges.push(record)
}
}
function reconcile() {
topo.objects.districts.geometries.forEach(function(geo) {
geo.properties.judges = []
if(geo.properties.name === null) return;
var parts = geo.properties.name.split(' '),
geostate = null,
geolocation = null
if(parts.length > 1) {
geolocation = parts.pop()
geostate = parts.join(' ')
} else {
geostate = parts[0]
}
judges.forEach(function(judge) {
var cname = judge['Court Name'],
info = {
name: judge['Judge First Name'] + " " + judge['Judge Last Name'],
ppa: judge['Party Affiliation of President']
// race: judge['Race or Ethnicity'],
// gender: judge['Gender'],
// date: judge['Commission Date']
}
if(cname.indexOf(geostate) !== -1 && (geolocation && cname.indexOf(geolocation) !== -1)) {
geo.properties.judges.push(info)
} else if(!geolocation && cname.indexOf(geostate) != -1) {
geo.properties.judges.push(info)
}
})
})
console.log(JSON.stringify(topo));
}
csv.fromPath('build/states.csv', { headers: true })
.on('record', function(state) { states.push(state) })
.on('end', function() {
csv.fromPath('build/judges.csv', { headers: true })
.on('record', terminated)
.on('end', reconcile)
})
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment