block by dhoboy 3d87de4a03a4c7f7797b515af0b8589f

Lyme Disease Chloropleth 2

Full Screen

Alternate version of Lyme Disease Chloropleth. All four datasets shown at once. Hover over a county on a map to see cooresponding readings for that county on the other maps. I left a question in the comments on this block starting at line 118.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>
 .county {
   stroke: #e8e8e8;
   stroke-width: 1px;
   stroke-linejoin: round;
   stroke-opacity: 0.1;
 }
.container {
  margin-top: 20px;
  margin-left: 20px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  max-width: 950px;
}
.calendar{
  width: 450px;
}
.calendarTitle {
  font-size: 14px;
  font-family: "Futura", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

</style>
<body>
<div class="container"></div>
<script src="//d3js.org/d3.v3.js"></script>
<script>
var width = 400,
    height = 250;

var stateFIPS = { "01": { "abbrev": "AL", "name": "Alabama" }, "02": { "abbrev": "AK", "name": "Alaska" }, "05": { "abbrev": "AR", "name": "Arkansas" }, "60": { "abbrev": "AS", "name": "American Samoa" }, "04": { "abbrev": "AZ", "name": "Arizona" }, "06": { "abbrev": "CA", "name": "California" }, "08": { "abbrev": "CO", "name": "Colorado" }, "09": { "abbrev": "CT", "name": "Connecticut" }, "11": { "abbrev": "DC", "name": "District of Columbia" }, "10": { "abbrev": "DE", "name": "Delaware" }, "12": { "abbrev": "FL", "name": "Florida" }, "13": { "abbrev": "GA", "name": "Georgia" }, "66": { "abbrev": "GU", "name": "Guam" }, "15": { "abbrev": "HI", "name": "Hawaii" }, "19": { "abbrev": "IA", "name": "Iowa" }, "16": { "abbrev": "ID", "name": "Idaho" }, "17": { "abbrev": "IL", "name": "Illinois" }, "18": { "abbrev": "IN", "name": "Indiana" }, "20": { "abbrev": "KS", "name": "Kansas" }, "21": { "abbrev": "KY", "name": "Kentucky" }, "22": { "abbrev": "LA", "name": "Louisana" }, "25": { "abbrev": "MA", "name": "Massachusetts" }, "24": { "abbrev": "MD", "name": "Maryland" }, "23": { "abbrev": "ME", "name": "Maine" }, "26": { "abbrev": "MI", "name": "Michigan" }, "27": { "abbrev": "MN", "name": "Minnesota" }, "29": { "abbrev": "MO", "name": "Missouri" }, "28": { "abbrev": "MS", "name": "Mississippi" }, "30": { "abbrev": "MT", "name": "Montana" }, "37": { "abbrev": "NC", "name": "North Carolina" }, "38": { "abbrev": "ND", "name": "North Dakota" }, "31": { "abbrev": "NE", "name": "Nebraska" }, "33": { "abbrev": "NH", "name": "New Hampshire" }, "34": { "abbrev": "NJ", "name": "New Jersey" }, "35": { "abbrev": "NM", "name": "New Mexico" }, "32": { "abbrev": "NV", "name": "Nevada" }, "36": { "abbrev": "NY", "name": "New York" }, "39": { "abbrev": "OH", "name": "Ohio" }, "40": { "abbrev": "OK", "name": "Oklahoma" }, "41": { "abbrev": "OR", "name": "Oregon" }, "42": { "abbrev": "PA", "name": "Pennsylvania" }, "72": { "abbrev": "PR", "name": "Puerto Rico" }, "44": { "abbrev": "RI", "name": "Rhode Island" }, "45": { "abbrev": "SC", "name": "South Carolina" }, "46": { "abbrev": "SD", "name": "South Dakota" }, "47": { "abbrev": "TN", "name": "Tennessee" }, "48": { "abbrev": "TX", "name": "Texas" }, "49": { "abbrev": "UT", "name": "Utah" }, "51": { "abbrev": "VA", "name": "Virginia" }, "78": { "abbrev": "VI", "name": "Virgin Islands" }, "50": { "abbrev": "VT", "name": "Vermont" }, "53": { "abbrev": "WA", "name": "Washington" }, "55": { "abbrev": "WI", "name": "Wisconsin" }, "54": { "abbrev": "WV", "name": "West Virginia" }, "56": { "abbrev": "WY", "name": "Wyoming" } };

var countyFIPS = {}; 

var projection = d3.geo.albersUsa()
  .scale(500)
  .translate([width/2, height/2]);

var path = d3.geo.path()
  .projection(projection);

var color = d3.scale.quantile()
  .domain([0,10,100,1000,10000])
  .range(["#74c476","#41ab5d","#238b45","#006d2c","#00441b"]);

var dateRanges = ["1992_1996", "1997_2001", "2002_2006", "2007_2011"];

var calendarContainer = d3.select(".container").selectAll(".calendar")
  .data(dateRanges)
  .enter()
  .append("div")
  .attr("class", function(d) { return "calendar"; });
  
var calendarTitle = calendarContainer.append("div")
  .attr("class", "calendarTitle")
  .text(function(d) { return d.split("_").join(" - "); });

var svg = calendarContainer.append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", function(d) { return "yr" + d; });

var counties = {}, lyme = {}, remaining = 2;

d3.json("us_counties.json", function(err, data) {
  counties = data;
  if (!--remaining) draw();
});

d3.csv("LymeDisease_9211_county.csv", function(err, data) {
  lyme = data;
  if (!--remaining) draw();
});

function draw() {
  countyFIPS = d3.nest()
    .key(function(d) { return d.properties.STATEFP; }) // nest by state
    .entries(counties.features);

  countyFIPS = countyFIPS.map(function(d) {
    return { "state": d.key, "counties": d.values.reduce(function(prev, next) {
        prev[next.properties.COUNTYFP] = next.properties.NAME;
        return prev;
      }, {})
    };
  }).reduce(function(prev, next) {
    prev[next.state] = next.counties;
    return prev;
  }, {});

  lyme = d3.nest()
    .key(function(d) { return d.StateCode.length == 1 ? "0" + d.StateCode : d.StateCode; })
    .entries(lyme);

  lyme = lyme.map(function(d) {
    return { "state": d.key, "counties": d.values.reduce(function(prev, next) {
        var cc = "";
        if (next.CountyCode.length == 1) { 
          cc = "00" + next.CountyCode; 
        } else if (next.CountyCode.length == 2) {
          cc = "0" + next.CountyCode;
        } else {
          cc = next.CountyCode;
        }

        prev[cc] = next;
        return prev;
      }, {})
    };
  }).reduce(function(prev, next) {
    prev[next.state] = next.counties;
    return prev;
  }, {});

  svg.selectAll(".county")  /* question here... kai says this: another way to access parent data from a child is `d3.select(this[0][0].parentNode).data() */
    .data(function(previous_d) { 
      var whynot = counties.features.map(function(f) {
        /* option 1 
        if (!f.yearRange) {
          f.yearRange = previous_d;
        } // this code sets f.yearRange = "1992_1996" for all counties on all 4 calendars
        */
        
        /* option 2
        f.yearRange = previous_d; // this code sets f.yearRange = "2007_2011" for all counties on all 4 calendars
        */
        return f;
      })
      return whynot;
    })
    .enter()
    .append("path")
    .attr("class", function(d, i) { return "county"; })
    .attr("d", path);

    /* instead, I chose this way of coloring the calendars in. */
    dateRanges.forEach(function(yearRange) { 
      calendarContainer.select("svg.yr" + yearRange).selectAll(".county")
        .style("fill", function(d) { 
          var p = d.properties; 
          return ((lyme[p.STATEFP] && lyme[p.STATEFP][p.COUNTYFP] && lyme[p.STATEFP][p.COUNTYFP]["ConfirmedCount_" + yearRange] != "") ? color(+lyme[p.STATEFP][p.COUNTYFP]["ConfirmedCount_" + yearRange]) : "#e0e0e0"); 
        })
        .on("mouseover", function(d) {
          filterAll(d);
        })
    });
}

function filterAll(d) {
  var p = d.properties;
  var readings = [];
  dateRanges.forEach(function(yearRange) {
    var r = {};
    r.yearRange = yearRange;
    r.county = countyFIPS[p.STATEFP][p.COUNTYFP] + " County, " + stateFIPS[p.STATEFP].name;
    if (lyme[p.STATEFP] && lyme[p.STATEFP][p.COUNTYFP] && lyme[p.STATEFP][p.COUNTYFP]["ConfirmedCount_" + yearRange] != "") { // valid reading for this county at this year range
      var l = lyme[p.STATEFP][p.COUNTYFP]["ConfirmedCount_" + yearRange];
      r.reading = l + (l == "1" ? " confirmed case" : " confirmed cases");
    } else {
      r.reading = "No Data";
    }
    readings.push(r);
  });

  calendarTitle
    .data(readings)
    .text(function(d) { 
      return d.yearRange.split("_").join(" - ") + ": " + d.county + ", " + d.reading;
    });
}

</script>