Skip to content

Instantly share code, notes, and snippets.

@ngchwanlii
Last active March 4, 2017 04:33
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 ngchwanlii/7e98ba2c59d3d692bf63387c6a64c894 to your computer and use it in GitHub Desktop.
Save ngchwanlii/7e98ba2c59d3d692bf63387c6a64c894 to your computer and use it in GitHub Desktop.
Double Sides Bar Chart - Florida Gun Deaths
height: 1200

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

<!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="bars"></g> <!-- heavy black axis lines -->
<g id="note"></g> <!-- area annotation -->
</g>
<g id="legend"></g>
</svg>
<script>
var size = {width: 750, height: 800};
var pad = {top: 120, right: 45, bottom: 75, left: 60};
var offset = 8;
var width = size.width - pad.left - pad.right;
var height = size.height - pad.top - pad.bottom + offset;
var x = d3.scaleBand()
.range([0, width])
.paddingInner(0.01);
var y = d3.scaleLinear()
.range([height, 0]);
var xaxis = d3.axisTop(x)
.tickValues([1990, 1995, 2000, 2005, 2010, 2015])
// .ticks(6)
.tickFormat(function(d) { return d; })
// hide end tick
.tickSizeOuter(0);
var yaxis = d3.axisLeft(y)
.ticks(10)
.tickPadding(5)
.tickSizeOuter(0)
.tickSizeInner(-width); // drawing the grid line
function translate(x, y) {
return "translate(" + x + "," + y + ")";
}
function convert(row) {
row.Year = +row.Year;
row.Total = +row.Total;
row.Diff = +row["Difference in 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));
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 + offset)
.attr("dx", "5px")
.attr("dy", "-23pt")
.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://tintickyurl.com/led8ggk");
d3.csv("rateDiff.csv", convert, function(error, data) {
if (error) throw error;
// x.domain(d3.extent(data, function(e) {return e.Year;}));
x.domain(data.map(function(d){return d.Year}).reverse())
y.domain(d3.extent(data, function(d){return d.Diff})).nice();
var colors = d3.scaleLinear()
.domain(d3.extent(data, function(d){
return d.Total;
}))
.interpolate(d3.interpolateRgb)
// "#e0f3db": light_teal, #43a2ca: blue in Tableau Color Theme. Details: http://colorbrewer2.org/#type=sequential&scheme=GnBu&n=3
.range(["#8a0707"]);
var bars = plot.select("#bars")
.selectAll("rect")
.data(data);
bars.enter().append("rect")
.attr("class", "bar")
.attr("width", x.bandwidth())
.attr("x", function(d) {
return x(d.Year);
})
.attr("y", function(d){
return y(d.Diff) < y(0) ? y(d.Diff): y(0) + 2;
})
.attr("height", function(d) {
return y(d.Diff) < y(0) ? y(0)-y(d.Diff) - 1 : y(d.Diff) - y(0);
})
.attr("fill", function(d){return colors(d.Total)});
/*
* draw x- and y-axis
* should be behind other elements
*/
svg.select("g#y")
.attr("transform", translate(pad.left-2, pad.top))
.call(yaxis)
.selectAll("g.tick")
.filter(function(d) {return d == 0})
.select("line")
.style("stroke-dasharray", 0)
.style("stroke", "black")
.style("stroke-width", 3);
// slighltly adjust the header and footer
svg.select("g#header")
.attr("transform", translate(pad.left, 0))
svg.select("g#footer")
.attr("transform", translate(pad.left, 0))
svg.select("g#x")
.attr("transform", translate(pad.left, pad.top-2))
.call(xaxis)
.selectAll(".tick text")
.style("text-anchor", "middle")
// .attr("x", data.map(function(d){return x(d.Year)}))
.attr("x", 0)
.attr("y", 0)
.attr("dy", "-0.6em");
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(1994))
.attr("y", y(0.65))
.attr("dx", x(1995) - x(1996))
.attr("dy", function(d, i) { return (-i * 2) + "ex"; })
.text(function(d) {
return d;
});
note.append("line")
.attr("x1", x(2000))
.attr("x2", x(2005))
.attr("y1", y(0.6))
.attr("y2", y(0.35));
svg.select("g#legend")
.attr("transform", translate(0, size.height/2))
.append("text")
.attr("dx", "-5em")
.attr("transform", "rotate(90)")
.text("Number of Gun Deaths");
});
</script>
</body>
</html>
Year Total Difference in Rate
2015 767 0.333644329
2014 690 -0.076668045
2013 696 -0.16613576
2012 721 0.12482026
2011 691 0.091245915
2010 669 -0.142708687
2009 695 -0.440772449
2008 780 -0.269057821
2007 825 0.383513142
2006 740 1.125234559
2005 521 -0.260745466
2004 555 -0.264220793
2003 586 0.122197362
2002 552 0.236653225
2001 502 -0.048419275
2000 499 0.119977507
1999 460 -0.924331132
1998 589 -0.382594907
1997 634 -0.326029681
1996 668 -0.220191122
1995 687 -0.469269519
1994 739 -0.55399635
1993 800 0.001273263
1992 789 -0.230583063
1991 806 -0.530835933
1990 873 -0.300184289
1989 888
body {
margin: 5px;
padding: 0px;
text-align: center;
}
text {
font-family: 'Fira Sans', sans-serif;
font-weight: 400;
font-size: 12pt;
}
#x line,
#y line {
stroke: black;
}
#y .tick line {
stroke-dasharray: 2px;
}
rect .bar {
fill: red;
}
#x path,
#y path {
stroke: black;
stroke-width: 2px;
}
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: black;
}
#note #note-2 {
font-weight: 500;
}
#note line {
stroke: black;
stroke-width: 2px;
stroke-opacity: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment