Skip to content

Instantly share code, notes, and snippets.

@gelicia
Last active December 19, 2015 22:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gelicia/6025562 to your computer and use it in GitHub Desktop.
Save gelicia/6025562 to your computer and use it in GitHub Desktop.
once more with feeling
{"description":"once more with feeling","endpoint":"","display":"svg","public":true,"require":[{"name":"underscore","url":"http://underscorejs.org/underscore-min.js"}],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"map.geojson":{"default":true,"vim":false,"emacs":false,"fontSize":12},"newyork.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/2SZsiLN.png"}
/*Occasionally there is a race condition where the map loads before
the bar chart, so the map-to-barchart highlighting doesn't work.
Hit space on this side to fix it.
It happens very rarely. In real life I would fix it with
jquery deferred but underscore defer works well enough for now.
This is also full of magic numbers, more external styling and
config variables would fix that.
*/
var map = tributary.newyork;
var svg = d3.select('svg');
var data = [];
var bounds = {l : 768, h: 366};
var mapG = svg.append('g').attr("id", "mapG");
var path = d3.geo.path().projection(
d3.geo.mercator().center([ -74.1, 40.7]).
scale(34348).translate([bounds.l / 2, bounds.h / 2]));
var mapPath = mapG.selectAll('path.shapes')
.data(map.features)
.enter().append('path')
.attr({
'class': 'shape',
'd': path,
'id': function(d){return "p"+ d.properties.Precinct;}
})
.style('fill', '#BBBBF8')
.style('stroke', "black");
d3.json('http://data.cityofnewyork.us/resource/2j99-6h29.json',
function(error, json) {
//standardize the precinct to be just a number or undefined
json = json.map(function(d){
if (isNaN(d.police_precinct.substring(9, d.police_precinct.length))){
d.police_precinct = undefined;
}
else {
d.police_precinct = Number(d.police_precinct.substring(9, d.police_precinct.length));
}
return d;
});
//group the set to be by precinct, totaling the number of reports and averaging the
//number of days a report goes unresolved
for (var i = 0; i < json.length; i++) {
var graffEntry = json[i];
if (graffEntry.police_precinct !== undefined){
var entry = _.find(data, function(d){ return d.precinct == graffEntry.police_precinct;});
if (entry === undefined){ //create
var thisPre = {};
thisPre.precinct = graffEntry.police_precinct;
thisPre.avgResolveDays = 0;
thisPre.numUnresolved = 0;
thisPre.numTotal = 0;
data.push(thisPre);
entry = data[data.length-1];
}
entry.numTotal = entry.numTotal + 1;
var resolved = graffEntry.status == 'Closed' ? true : false;
//closed_date seems to be filled for closed entries, otherwise don't trust status
//just trust closed_date
if(resolved){
// difference in days
var dateDiff = (graffEntry.closed_date - graffEntry.created_date)/60/60/24;
if (entry.avgResolveDays === 0) { entry.avgResolveDays = dateDiff;}
else {
entry.avgResolveDays = (entry.avgResolveDays + dateDiff)/2;
}
}
else {
entry.numUnresolved = entry.numUnresolved + 1;
}
}
}
//display the bars sorted by desc avgResolveDays
data = data.sort(function(a, b) {
return a.avgResolveDays < b.avgResolveDays ? 1 : -1;
});
var graphGrp = svg.append('g')
.attr('transform', 'translate(36, 360)');
var barWidth = 8;
var valMax = d3.max(data, function(d){return d.avgResolveDays});
var heightScale = d3.scale.linear().domain([0, valMax])
.range([0, 200]);
graphGrp.append('text')
.attr({
x: 213,
y: 50,
'font-size': 14
})
.text('Average Days To Resolve a Report');
graphGrp.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr({
'id': function(d){return 'b'+d.precinct;},
x: function(d,i){return (i*(barWidth + 2));},
y: function(d){return 30 - heightScale(d.avgResolveDays);},
height: function(d){return heightScale(d.avgResolveDays);},
width: barWidth,
fill: '#FFC78A'
})
.on('mouseover', function(d){
d3.select(this)
.style('fill', '#FF9A2C');
d3.select('#p' + d.precinct)
.style('fill', '#6C6CED');
})
.on('mouseout', function(d){
d3.select(this)
.style('fill', '#FFC78A');
d3.select('#p' + d.precinct)
.style('fill', '#BBBBF8');
})
.on('click', function(d){
var entry = _.find(data, function(dIn){ return dIn.precinct == d.precinct;});
clickPrec(entry);
});
//fixes a race condition where the map draws before the bars
//then the map to bar highlighting doesn't work
_.defer(function(){
mapPath
.on('mouseover', function(d){
d3.select(this)
.style('fill', '#6C6CED');
d3.select('#b' + d.properties.Precinct)
.style('fill', '#FF9A2C');
})
.on('mouseout', function(d){
d3.select(this)
.style('fill', '#BBBBF8');
d3.select('#b' + d.properties.Precinct)
.style('fill', '#FFC78A');
})
.on('click', function(d){
var entry = _.find(data, function(dIn){ return dIn.precinct == d.properties.Precinct;});
clickPrec(entry);
});
});
});
//swaps out an informational box
function clickPrec(entry){
d3.select('g.clkInfo').remove();
var infoTxt = svg.append('g')
.classed('clkInfo', true)
.attr('transform', 'translate(50, 50)').append('text');
if(entry !== undefined){
infoTxt.append('tspan')
.classed('headline', true)
.text('Police Precinct ' + entry.precinct);
infoTxt.append('tspan')
.attr({
x : 0,
dy : '1.2em'
})
.text(Math.round(entry.avgResolveDays) + " average days to resolve a report.");
infoTxt.append('tspan')
.attr({
x : 0,
dy : '1.2em'
})
.text(entry.numTotal + " reports (" + entry.numUnresolved + " unresolved)");
}
else {
infoTxt.text('No information available for this precinct.');
}
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
.headline {
font-weight: bold
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment