Skip to content

Instantly share code, notes, and snippets.

@jalague
Last active March 3, 2017 22:55
Show Gist options
  • Save jalague/ee46a62df3095fb5bd15e04cc69e68ff to your computer and use it in GitHub Desktop.
Save jalague/ee46a62df3095fb5bd15e04cc69e68ff to your computer and use it in GitHub Desktop.
Florida Gun Deaths John
height: 750

Florida Gun Deaths

This block provides a rough re-creation of the Florida Gun Deaths visualization. Keeping in mind the inspiration and issues discussed, try to redesign this visualization. Focus first on editing the style (colors, thickness of lines, etc.) before changing the encoding.

Original Visualization

The original visualization appeared in the article This Chart Shows An Alarming Rise In Florida Gun Deaths After 'Stand Your Ground' Was Enacted article by Pamela Engel on Business Insider on February 18, 2014.

The chart was created by Christine Chen. She responded to the discussion, and linked to her inspiration for the graphic. This inspiration appeared in the infographic Iraq's bloody toll by Simon Scarr on South China Morning Post on December 17, 2011.

Online Discussion

There was a lot of discussion, especially on Twitter and various blogs, when this visualization came out. Here are some of those posts:

Original Data

You can access the original (and updated) data for this visualization from the Florida Statistical Analysis Center. Specifically, you can download the "Murder: Firearm Type and Rate for Florida" dataset in PDF or Excel format the UCR Offense Data page.

Trifacta Recipe

To generate the data.csv file, the original 1971_fwd_murder_firearms.xlsx file was transformed using the following Trifacta Wrangler recipe:

splitrows col: column1 on: '\n' quote: '\"'
delete row: IN(SOURCEROWNUMBER(), [1,2])
split col: column1 on: ',' limit: 11 quote: '\"'
replace col: * with: '' on: '\"' global: true
header
delete row: SOURCEROWNUMBER() == 4
drop col: Total_Murders, Murder_Rate_per_100_000, Total_Handgun, Total_Other_Firearm, Total_Percent_by_Firearms, Percent_by_Handguns, Percent_by_Other_Firearms, Total_by_Firearm_change, Population_Change
rename col: Total_by_Firearm to: 'Total'
delete row: IN(SOURCEROWNUMBER(), [50, 57, 51, 52, 53, 54, 55, 56])
keep row: (DATE(1989, 1, 1) <= Year) && (Year < DATE(2017, 1, 1))
derive value: Total / (Population / 100000) as: 'Rate'

forked from sjengle's block: Florida Gun Deaths

Year Population Total Rate
1989 12797318 888 6.938953927690162
1990 13150027 873 6.6387696390281175
1991 13195952 806 6.107933705730363
1992 13424416 789 5.877350642292373
1993 13608627 800 5.878623905262448
1994 13878905 739 5.324627555271832
1995 14149317 687 4.855358036009795
1996 14411563 668 4.635166914234077
1997 14712922 634 4.309137233242995
1998 15000475 589 3.9265423261596717
1999 15322040 460 3.002211193809701
2000 15982378 499 3.1221887005801015
2001 16331739 502 3.0737694252890035
2002 16674608 552 3.310422649815816
2003 17071508 586 3.432620012244964
2004 17516732 555 3.1683992196717976
2005 17918227 521 2.9076537539121476
2006 18349132 740 4.032888313191054
2007 18680367 825 4.416401455067772
2008 18807219 780 4.147343634377842
2009 18750483 695 3.706571185392931
2010 18771768 669 3.5638624981940965
2011 18905048 691 3.6551084133719205
2012 19074434 721 3.779928673112922
2013 19259543 696 3.613792912947104
2014 19507369 690 3.5371248680434557
2015 19815183 767 3.870769197539079
<!DOCTYPE html>
<meta charset="utf-8">
<link href='https://fonts.googleapis.com/css?family=Fira+Sans:300,400,500,700' rel='stylesheet' type='text/css'>
<link href='style.css' rel='stylesheet' type='text/css'>
<script src="//d3js.org/d3.v4.min.js"></script>
<body>
<!--
If there is an order you prefer for your elements,
consider pre-defining the g elements in your
preferred order.
//-->
<svg>
<!-- axis lines should be in back -->
<g id="x"></g> <!-- x axis -->
<g id="y"></g> <!-- y axis -->
<!-- header (title) and footer (source) -->
<g id="header"></g>
<g id="footer"></g>
<!-- actual visualization on top -->
<g id="plot">
<g id="area"></g> <!-- area chart -->
<g id="note"></g> <!-- area annotation -->
<g id="line"></g> <!-- line chart -->
<g id="points"></g> <!-- line markers -->
<g id="bars"></g> <!-- heavy black axis lines -->
</g>
</svg>
<script>
var size = {width: 600, height: 750};
var pad = {top: 100, right: 45, bottom: 75, left: 45};
var width = size.width - pad.left - pad.right;
var height = size.height - pad.top - pad.bottom;
var x = d3.scaleLinear()
.range([0, width]);
var y = d3.scaleLinear()
.range([0, height]);
var xaxis = d3.axisBottom(x)
.tickSize(20, 0)
.tickValues([1990, 2000, 2010])
.tickFormat(function(d) { return "" + d + "s"; });
var yaxis = d3.axisLeft(y)
.ticks(6)
var line = d3.line()
.curve(d3.curve)
.x(function(d) { return x(d.Year); })
.y(function(d) { return y(d.Total); });
var area = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.Year); })
.y1(0)
.y0(function(d) { return y(d.Total); });
function translate(x, y) {
return "translate(" + x + "," + y + ")";
}
function convert(row) {
row.Year = +row.Year;
row.Population = +row.Population;
row.Total = +row.Total;
row.Rate = +row.Rate;
return row;
}
var svg = d3.select("body").select("svg");
var plot = svg.select("g#plot");
var header = svg.select("g#header");
var footer = svg.select("g#footer");
svg.attr("width", size.width);
svg.attr("height", size.height);
plot.attr("transform", translate(pad.left, pad.top));
/*
* add various text annotation to svg
*/
header.append("text")
.attr("class", "title")
.attr("x", 0)
.attr("y", 0)
.attr("dx", "5px")
.attr("dy", "36pt")
.text("Gun deaths in Florida");
header.append("text")
.attr("class", "subtitle")
.attr("x", 0)
.attr("y", 0)
.attr("dx", "5px")
.attr("dy", "58pt")
.text("Number of murders committed using firearms");
footer.append("text")
.attr("x", 0)
.attr("y", size.height)
.attr("dx", "5px")
.attr("dy", "-22pt")
.text("Source: Florida Department of Law Enforcement");
footer.append("text")
.attr("x", 0)
.attr("y", size.height)
.attr("dx", "5px")
.attr("dy", "-6pt")
.text("Inspiration: http://tinyurl.com/led8ggk");
/*
* draw heavy axis lines at y-min and y-max
*/
var bars = plot.select("g#bars");
bars.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", width)
.attr("y2", 0)
bars.append("line")
.attr("x1", 0)
.attr("y1", height)
.attr("x2", width)
.attr("y2", height);
d3.csv("data.csv", convert, function(error, data) {
if (error) throw error;
console.log(data);
x.domain(d3.extent(data, function(e) {return e.Year; }));
y.domain([0, 1000]);
/*
* draw x- and y-axis
* should be behind other elements
*/
svg.select("g#y")
.attr("transform", translate(pad.left, pad.top))
.call(yaxis);
svg.select("g#x")
.attr("transform", translate(pad.left, pad.top + height))
.call(xaxis)
.selectAll(".tick text")
.style("text-anchor", "start")
.attr("x", 6)
.attr("y", 6);
/*
* plot red area
*/
plot.select("g#area")
.append("path")
.datum(data)
.attr("d", area)
.style("fill", 'red')
/*
* draw line on top of area
*/
/*
plot.select("g#line")
.append("path")
.datum(data)
.attr("d", line);
*/
/*
* draw points on top of line
*/
/*
plot.select("g#points")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return x(d.Year); })
.attr("cy", function(d) { return y(d.Total); })
.attr("r", 6);
*/
/*
* plot annotation on top of area
*/
var note = plot.select("g#note");
note.selectAll("text")
// text with manual line breaks
.data(["2005", "Florida enacted", "its 'Stand Your", "Ground' law"].reverse())
.enter()
.append("text")
.attr("id", function(d, i) { return "note-" + i; })
.attr("x", x(2000))
.attr("y", y(840))
.attr("dx", x(2002) - x(2005))
.style('fill', 'black')
.attr("dy", function(d, i) { return (-i * 2) + "ex"; })
.text(function(d) { return d; });
note.append("line")
.style('fill', "black")
.attr("x1", x(2002))
.attr("x2", x(2005))
.attr("y1", y(700) + 5)
.attr("y2", y(521))
.style("stroke", 'black');
});
</script>
</body>
</html>
body {
margin: 5px;
padding: 0px;
text-align: center;
}
text {
font-family: 'Fira Sans', sans-serif;
font-weight: 400;
font-size: 12pt;
}
#area path {
fill: #970008;
fill-opacity: 0.85;
stroke: none;
}
#line path {
fill: none;
stroke: black;
stroke-width: 4;
}
#points circle {
fill: black;
stroke: white;
stroke-width: 1.5;
}
#y path,
#x path {
fill: none;
stroke: none;
}
#y line {
stroke: #A6A2A1;
stroke-width: 2.25;
stoke-opacity: 0.25;
}
#x line,
#bars {
stroke: black;
stroke-width: 2.25;
}
text.title {
font-weight: 700;
font-size: 36pt;
}
text.subtitle {
font-weight: 300;
font-size: 18pt;
}
#note text {
font-weight: 300;
font-size: 18pt;
fill: white;
}
#note #note-3 {
font-weight: 500;
}
#note line {
stroke: white;
stroke-width: 2px;
stroke-opacity: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment