This data is from NYC Open Data. The original file covers 2012 to the present and has more than 1 million rows.
This gist also contains the R script used to process the data:
Note the reversed seasonal trends. While the cyclist injury/death follows the expected trend (due to more cyclists during warmer weather), for pedestrians the trend is reversed. This could be for a number of factors (e.g., lower light during winter, snow/ice on the ground, etc.) and warrants further investigation.
forked from curran's block: Customized Axes
forked from jpasini's block: Near-Earth Comets - Orbital Elements
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
<title>Pedestrian and cyclists injured or killed in collisions</title>
<style>
@import url('https://fonts.googleapis.com/css?family=Roboto');
body {
margin: 0px;
font-family: Roboto;
}
.tick {
font-size: 2em;
}
.axis line {
stroke: #ccc;
}
.axis text {
fill: #666;
}
.axis-label {
fill: #666;
font-size: 2.5em;
}
.comet {
opacity: 0.4;
}
.comet:hover {
opacity: 1;
fill: #ffa251;
}
.schwassman {
opacity: 0.7;
}
.long {
opacity: 0.5;
}
.plotTitle {
font-size: 1.5em;
fill: #666;
}
.legend-label {
fill: #666;
}
.color-legend, .r-legend {
font-size: 1.2em;
fill: #666;
}
.line {
fill: none;
stroke-width: 2px;
}
</style>
</head>
<body>
<svg width="960" height="500"></svg>
<script>
const xValue = d => d.MONTH_NUM;
const y1Value = d => d.PERCENT_CYCLIST;
const y2Value = d => d.PERCENT_PEDESTRIAN;
const colorValue = d => d.YEAR;
const xLabel = 'Month';
const yLabel = '% with injury or death to ...';
const margin = { left: 100, right: 140, top: 60, bottom: 120 };
const svg = d3.select('svg');
const width = svg.attr('width');
const height = svg.attr('height');
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
g.append("text")
.attr("x", (innerWidth / 2))
.attr("y", -20)
.attr("text-anchor", "middle")
.attr('class', 'plotTitle')
.text("% collisions with injury or death to a ...");
const xAxisG = g.append('g')
.attr('transform', `translate(0, ${innerHeight})`)
.attr('class', 'axis');
const yAxisG = g.append('g')
.attr('class', 'axis');
const colorLegendG = g.append('g')
.attr('transform', `translate(${innerWidth+40}, ${innerHeight/3})`);
const shapeLegendG = g.append('g')
.attr('transform', `translate(${innerWidth+20}, 20)`);
xAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', innerWidth/2)
.attr('y', 60)
.text(xLabel);
const xScale = d3.scaleLinear();
const yScale = d3.scaleLinear();
const colorScale = d3.scaleOrdinal(d3["schemeCategory10"])
.domain([2013, 2014, 2015, 2016])
const months = {1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Dec"};
const xAxis = d3.axisBottom()
.scale(xScale)
.tickPadding(10)
.tickSize(-innerHeight)
.tickFormat(d => months[d]);
const yAxis = d3.axisLeft()
.scale(yScale)
.ticks(5)
.tickPadding(20)
.tickSize(-innerWidth);
const colorLegend = d3.legendColor()
.scale(colorScale)
.shapePadding(10)
.shape('circle');
const row = d => {
d.YEAR = +d.YEAR;
d.MONTH_NUM = +d.MONTH_NUM;
d.PERCENT_CYCLIST = +d.PERCENT_CYCLIST;
d.PERCENT_PEDESTRIAN = +d.PERCENT_PEDESTRIAN;
return d;
};
d3.csv('collision_damage_fractions_comparison.csv', row, data => {
xScale
.domain(d3.extent(data, xValue))
.range([0, innerWidth])
.nice();
yScale
.domain([0, d3.max(data, y2Value)])
.range([innerHeight, 0])
.nice();
const circle_r = 8;
const square_side = 14;
const opacity = 0.6;
g.selectAll('.cyclists').data(data)
.enter().append('circle')
.attr('cx', d => xScale(xValue(d)))
.attr('cy', d => yScale(y1Value(d)))
.attr('r', circle_r)
.attr('opacity', opacity)
.attr('fill', d => colorScale(colorValue(d)));
g.selectAll('.pedestrians').data(data)
.enter().append('rect')
.attr('x', d => xScale(xValue(d)) - square_side/2)
.attr('y', d => yScale(y2Value(d)) - square_side/2)
.attr('width', square_side)
.attr('height', square_side)
.attr('opacity', opacity)
.attr('fill', d => colorScale(colorValue(d)));
xAxisG.call(xAxis);
yAxisG.call(yAxis);
colorLegendG.call(colorLegend)
.attr('class', 'color-legend');
// add symbol legend by hand
g.append('rect')
.attr('x', d => xScale(10) - square_side/2 + 30)
.attr('y', d => yScale(7.8)- square_side/2)
.attr('width', square_side)
.attr('height', square_side)
.attr('opacity', opacity);
g.append('circle')
.attr('cx', d => xScale(10) + 30)
.attr('cy', d => yScale(7.3))
.attr('r', circle_r)
.attr('opacity', opacity);
g.append('text')
.attr('x', d => xScale(10) + 45)
.attr('y', d => yScale(7.8) + 5)
.text('pedestrian');
g.append('text')
.attr('x', d => xScale(10) + 45)
.attr('y', d => yScale(7.3) + 5)
.text('cyclist');
});
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js