Last active
July 10, 2016 18:43
-
-
Save mugshepherd/bc6b53152a9d47b3490e95af16398ade to your computer and use it in GitHub Desktop.
Pet Lemur Survey Visualization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This product includes color specifications and designs developed by Cynthia Brewer (http://colorbrewer.org/). | |
// JavaScript specs as packaged in the D3 library (d3js.org). Please see license at http://colorbrewer.org/export/LICENSE.txt | |
var colorbrewer = {Blues: { | |
3: ["#deebf7","#9ecae1","#3182bd"], | |
4: ["#eff3ff","#bdd7e7","#6baed6","#2171b5"], | |
5: ["#eff3ff","#bdd7e7","#6baed6","#3182bd","#08519c"], | |
6: ["#eff3ff","#c6dbef","#9ecae1","#6baed6","#3182bd","#08519c"], | |
7: ["#eff3ff","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"], | |
8: ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#084594"], | |
9: ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"] | |
}}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<title></title> | |
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.26/dc.css"> | |
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css"> | |
<link rel="stylesheet" type="text/css" href="main.css"> | |
</head> | |
<body> | |
<!-- title row --> | |
<div class="container-fluid"> | |
<div class="row"> | |
<div class="col-xs-12 dc-data-count dc-chart" id="data-count"> | |
<h2>Reported sightings of pet lemurs in Madagascar | |
<small> | |
<span class="filter-count"></span> selected out of <span class="total-count"></span> records | | |
<a id="all" href="#">Reset All</a> | |
</span> | |
</small> | |
</h1> | |
</div> | |
</div> | |
<!-- month/year circle filteres, Regions and Provinces bar charts --> | |
<div class="row" id="control-row"> | |
<div class="col-xs-3 pie-chart"> | |
<h4>Year <small><a id="year">reset</a></small></h4> | |
<div class="dc-chart" id="chart-ring-year"></div> | |
</div> | |
<div class="col-xs-3 pie-chart"> | |
<h4>Month <small><a id="month" href="#">reset</a></small></h4> | |
<div class="dc-chart" id="chart-ring-month"></div> | |
</div> | |
<div class="col-md-6"> | |
<h4>Category <small><a id="category" href="#">reset</a></small></h4> | |
<div class="dc-chart" id="chart_row_category"></div> | |
</div> | |
<!-- <div class="col-xs-4"> | |
<h4>Regions <small><a id="admin2_chart" href="#">reset</a></small></h4> | |
<div id="chart_row_admin2"></div> | |
</div> | |
<div class="col-xs-4"> | |
<h4>Provinces <small><a id="admin1_chart" href="#">reset</a></small></h4> | |
<div id="chart_row_admin1"></div> | |
</div> --> | |
<!-- | |
<div class="col-xs-6"> | |
<h4>Breweries</h4> | |
<div id="map"></div> | |
</div> --> | |
</div> | |
<!-- categories, and maps (admin2 and admin1) --> | |
<div class="row"> | |
<!-- <div class="col-md-4"> | |
<h4>Category <small><a id="category" href="#">reset</a></small></h4> | |
<div class="dc-chart" id="chart_row_category"></div> | |
</div> --> | |
<div> | |
<!-- <div class="col-md-1"></div> --> | |
<div class="col-xs-3 col-md-3"> | |
<h4>Regions <small><a id="admin2_chart" href="#">reset</a></small></h4> | |
<div id="chart_row_admin2"></div> | |
</div> | |
<div class="col-xs-3 col-md-3"> | |
<h4>Map: Regions <small><a id="admin2_map" href="#">reset</a></small></h4> | |
<div id="map_admin2"></div> | |
</div> | |
</div> | |
<!-- <div class="col-md-1"></div> --> | |
<div> | |
<div class="col-xs-3 col-md-3"> | |
<h4>Provinces <small><a id="admin1_chart" href="#">reset</a></small></h4> | |
<div id="chart_row_admin1"></div> | |
</div> | |
<!-- <div class="col-xs-6 col-md-4"> --> | |
<!-- <div class="col-xs-6 col-md-4"> --> | |
<div class="col-xs-3 col-md-3"> | |
<h4>Map: Provinces <small><a id="admin1_map" href="#">reset</a></small></h4> | |
<div id="map_admin1"></div> | |
</div> | |
<!-- <div class="col-md-1"></div> --> | |
</div> | |
</div> | |
<br> | |
<div class="row"> | |
<div class="col-xs-12"> | |
<h4>Source Data</h4> | |
<table class="table table-bordered table-striped" id="data-table"> | |
<thead> | |
<tr class="header"> | |
<th>Month</th> | |
<th>Year</th> | |
<th>Category</th> | |
<th>Quantity</th> | |
<th>Region</th> | |
<th>Province</th> | |
</tr> | |
</thead> | |
</table> | |
</div> | |
</div> | |
</div> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.26/dc.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
<script src="colorbrewer.js" type="text/javascript" charset="utf-8" async defer></script> | |
<script src="index.js" type="text/javascript" charset="utf-8" async defer></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var admin2_KV, | |
admin1_KV, | |
lemur_category_KV, | |
row1_height, | |
row2_height, | |
map_height, | |
map_width, | |
item_width, | |
rowChartBarColor | |
//import data from survey, and provide values for codes returned from API ("KV" = key/value) | |
d3.json('https://lemursurvey.herokuapp.com/', function(error, data) { | |
month_KV = { | |
"no_response":"No response", | |
"i_dont_know":"I dont know", | |
"january":"Jan","february":"Feb","march":"Mar","april":"Apr","may":"May","june":"Jun","july":"July","august":"Aug","september":"Sept","october":"Oct","november":"Nov","december":"Dec" | |
}; | |
year_KV = { | |
"no_response":"No response", | |
"i_dont_know":"I don't know", | |
"2016":"2016","2015":"2015","2014":"2014","2013":"2013","2012":"2012","2011":"2011","2010":"2010","2009":"2009","2008":"2008","2007":"2007","2006":"2006","2005":"2005","2004":"2004","2003":"2003","2002":"2002","2001":"2001","2000":"2000","1999":"1999","1998":"1998","1997":"1997","1996":"1996","1995":"1995","1994":"1994","1993":"1993","1992":"1992","1991":"1991","1990":"1990","1989":"1989","1988":"1988","1987":"1987","1986":"1986","1985":"1985","1984":"1984","1983":"1983","1982":"1982","1981":"1981","1980":"1980","1979":"1979","1978":"1978","1977":"1977","1976":"1976","1975":"1975","1974":"1974","1973":"1973","1972":"1972","1971":"1971","1970":"1970","1969":"1969","1968":"1968","1967":"1967","1966":"1966","1965":"1965","1964":"1964","1963":"1963","1962":"1962","1961":"1961","1960":"1960" | |
// , | |
// "before_1960":"before 1960", | |
}; | |
quantity_KV = { | |
"no_answer":"No response", | |
"i_don_t_know":"I don't know", | |
"1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8","9":"9","10":"10","11":"11","12":"12","13":"13","14":"14","15":"15","16":"16","17":"17","18":"18","19":"19","20":"20" | |
,"more_than_20":"21 or more" | |
} | |
admin1_KV = { | |
"antananarivo":"Antananarivo","antsiranana":"Antsiranana","fianarantsoa":"Fianarantsoa","mahajanga":"Mahajanga","toamasina":"Toamasina","toliara":"Toliara","other":"Other","no_response":"No response" | |
}; | |
admin2_KV = { | |
"alaotra-mangoro":"Alaotra-Mangoro","amoron.i_mania":"Amoron'I Mania","analamanga":"Analamanga","analanjirofo":"Analanjirofo","androy":"Androy","anosy":"Anosy","atsimo-andrefana":"Atsimo-Andrefana","atsimo-atsinanana":"Atsimo-Atsinanana","atsinanana":"Atsinanana","betsiboka":"Betsiboka","boeny":"Boeny","bongolava":"Bongolava","diana":"Diana","haute_matsiatra":"Haute Matsiatra","ihorombe":"Ihorombe","itasy":"Itasy","melaky":"Melaky","menabe":"Menabe","sava":"Sava","sofia":"Sofia","vakinankaratra":"Vakinankaratra","vatovavy-fitovinany":"Vatovavy-Fitovinany","no_response":"No response","other":"Other" | |
}; | |
lemur_category_KV = { | |
"aye_aye":"Aye Aye","bamboo_lemur":"Bamboo lemur","brown_lemur":"Brown lemur","dwarf_lemur":"Dwarf lemur","fork_marked_lemur":"Fork marked lemur","giant_mouse_lemurs":"Giant mouse lemurs","greater_bamboo_lemur":"Greater bamboo lemur","indri":"Indri","mouse_lemur":"Mouse lemur","ring-tailed_lemur":"Ring-tailed lemur","ruffed_lemurs":"Ruffed lemurs","sifaka":"Sifaka","sportive_lemur":"Sportive lemur","woolly_lemur":"Woolly lemur","I_dont_remembe":"I don't remember","no_response":"No response","other":"Other" | |
} | |
var lemurData = data.responses; | |
var fullDateFormat = d3.time.format('%Y-%m-%d'); | |
var yearFormat = d3.time.format('%Y'); | |
var monthFormat = d3.time.format('%b'); | |
//normalize/parse data for dc.js | |
lemurData.forEach(function(d) { | |
d.count = +d.count; | |
d.lemurs_quantity = quantity_KV[d.lemurs_quantity]; | |
d.categoryName = lemur_category_KV[d.lemur_category]; | |
d.month = month_KV[d.month]; | |
d.year = year_KV[d.year]; | |
d.location_admin1_chart = admin1_KV[d.location_admin1]; | |
d.location_admin1_map = d.location_admin1; | |
d.location_admin2_chart = admin2_KV[d.location_admin2]; | |
d.location_admin2_map = d.location_admin2 | |
}); | |
//set crossfilter | |
var ndx = crossfilter(lemurData); | |
//create dimensions (x-axis values) | |
var quantityDim = ndx.dimension(function(d) {return d.lemurs_quantity}), | |
monthDim = ndx.dimension(function(d) {return d.month}), | |
yearDim = ndx.dimension(function(d) {return d.year}), | |
categoryNameDim = ndx.dimension(function(d) {return d.categoryName;}), | |
admin1ChartDim = ndx.dimension(function(d) {return d.location_admin1_chart}), | |
admin2ChartDim = ndx.dimension(function(d) {return d.location_admin2_chart}), | |
admin1MapDim = ndx.dimension(function(d) {return d.location_admin1_map}), | |
admin2MapDim = ndx.dimension(function(d) {return d.location_admin2_map}), | |
allDim = ndx.dimension(function(d) {return d;}); | |
//creating groups (y-axis values) | |
var all = ndx.groupAll(); | |
var countPerYear = yearDim.group().reduceCount(), | |
countPerMonth = monthDim.group().reduceCount(), | |
categoryGroup = categoryNameDim.group().reduceCount(), | |
admin1ChartGroup = admin1ChartDim.group().reduceCount(), | |
admin2ChartGroup = admin2ChartDim.group().reduceCount(), | |
admin1MapGroup = admin1MapDim.group().reduceCount(), | |
admin2MapGroup = admin2MapDim.group().reduceCount(); | |
//creating charts | |
var yearChart = dc.pieChart('#chart-ring-year'), | |
monthChart = dc.pieChart('#chart-ring-month'), | |
categoryChart = dc.rowChart("#chart_row_category"), | |
admin1Chart = dc.rowChart("#chart_row_admin1"), | |
admin2Chart = dc.rowChart("#chart_row_admin2"), | |
admin1Map = dc.geoChoroplethChart("#map_admin1"), | |
admin2Map = dc.geoChoroplethChart("#map_admin2"), | |
dataCount = dc.dataCount('#data-count'), | |
dataTable = dc.dataTable('#data-table'); | |
//set up maps | |
d3.json("mdg_admin1.json", function(admin1JSON) { | |
d3.json("mdg_admin2.json", function(admin2JSON){ | |
row1_height = 200; | |
row2_height = 400; | |
item_width = 300 | |
map_width = item_width; | |
map_height = row2_height; | |
rowChartBarColor = "#3182BD"; //3182BD | |
var projection = d3.geo.mercator(); | |
var path = d3.geo.path().projection(projection); | |
//set up scale and translate | |
var bounds, scale, offset; | |
projection.scale(1).translate([0,0]); | |
var bounds = path.bounds(admin1JSON); | |
var scale = .95 / Math.max((bounds[1][0] - bounds[0][0]) / map_width, (bounds[1][1] - bounds[0][1]) / map_height); | |
var offset = [(map_width - scale * (bounds[1][0] + bounds[0][0])) /2, (map_height - scale * (bounds[1][1] + bounds[0][1])) /2 ]; | |
projection.scale(scale).translate(offset); | |
////chart configuration. must be under map data import and set up. | |
admin1Map | |
.width(map_width) | |
.height(map_height) | |
.dimension(admin1MapDim) | |
.group(admin1MapGroup) | |
.colors(d3.scale.quantize().range(colorbrewer.Blues[7])) | |
.colorDomain([0, 200]) | |
.colorCalculator(function (d) { return d ? admin1Map.colors()(d) : '#ccc'; }) | |
.projection(projection) | |
.overlayGeoJson(admin1JSON.features, "mdg_adm1", | |
function(d) { | |
return d.properties.code; | |
}) | |
; | |
admin2Map | |
.width(map_width) | |
.height(map_height) | |
.dimension(admin2MapDim) | |
.group(admin2MapGroup) | |
.colors(d3.scale.quantize().range(colorbrewer.Blues[7])) | |
.colorDomain([0, 200]) | |
.colorCalculator(function (d) { return d ? admin2Map.colors()(d) : '#ccc'; }) | |
.projection(projection) | |
.overlayGeoJson(admin2JSON.features, "mdg_adm2", | |
function(d) { | |
return d.properties.code_adm2; | |
}) | |
; | |
//other charts | |
yearChart | |
.width(row1_height) | |
.height(row1_height) | |
.dimension(yearDim) | |
.group(countPerYear) | |
.innerRadius(20); | |
monthChart | |
.width(row1_height) | |
.height(row1_height) | |
.dimension(monthDim) | |
.group(countPerMonth) | |
.innerRadius(20) | |
.ordering(function(d){ | |
var order = { | |
'Jan':1,'Feb':2,'Mar':3,'Apr':4,'May':5,'Jun':6,'Jul':7,'Aug':8,'Sep':9,'Oct':10,'Nov':11,'Dec':12 | |
}; | |
return order[d.key]; | |
}) | |
; | |
categoryChart | |
.width(item_width) | |
.height(row1_height) | |
.dimension(categoryNameDim) | |
.group(categoryGroup) | |
.elasticX(true) | |
.margins({top: 10, left: 20, right: 10, bottom: 20}) | |
.colors(rowChartBarColor) | |
; | |
admin1Chart | |
.width(item_width) | |
.height(row2_height) | |
.dimension(admin1ChartDim) | |
.group(admin1ChartGroup) | |
.elasticX(true) | |
.margins({top: 10, left: 20, right: 10, bottom: 20}) | |
.colors(rowChartBarColor) | |
.ordering(function(d){ | |
var order = { | |
"Antananarivo":1,"Antsiranana":2,"Fianarantsoa":3,"Mahajanga":4,"Toamasina":5,"Toliara":6,"Other":7,"No response":8 | |
}; | |
return order[d.key]; | |
}) | |
; | |
admin2Chart | |
.width(item_width) | |
.height(row2_height) | |
.dimension(admin2ChartDim) | |
.group(admin2ChartGroup) | |
.elasticX(true) | |
.margins({top: 10, left: 20, right: 10, bottom: 20}) | |
.colors(rowChartBarColor) | |
.ordering(function(d){ | |
var order = { | |
"Alaotra-Mangoro":1,"Amoron'I Mania":2,"Analamanga":3,"Analanjirofo":4,"Androy":5,"Anosy":6,"Atsimo-Andrefana":7,"Atsimo-Atsinanana":8,"Atsinanana":9,"Betsiboka":10,"Boeny":11,"Bongolava":12,"Diana":13,"Haute Matsiatra":14,"Ihorombe":15,"Itasy":16,"Melaky":17,"Menabe":18,"Sava":19,"Sofia":20,"Vakinankaratra":21,"Vatovavy-Fitovinany":22,"No Data":23, "Other":24, "No response":25 | |
}; | |
return order[d.key]; | |
}) | |
; | |
dataCount | |
.dimension(ndx) | |
.group(all); | |
//data table | |
dataTable | |
.dimension(allDim) | |
.group(function (d) { return 'dc.js insists on putting a row here so I remove it using js'; }) | |
.size(100) | |
.columns([ | |
function (d) { return d.month; }, | |
function (d) { return d.year; }, | |
function (d) { return d.categoryName; }, | |
function (d) { return d.lemurs_quantity; }, | |
function (d) { return d.location_admin2_chart; }, | |
function (d) { return d.location_admin1_chart; }, | |
]) | |
.sortBy(function (d) { return d.month_and_year; }) | |
.order(d3.descending) | |
.on('renderlet', function (table) { | |
//each time table is rendered remove extra row dc.js insists on adding | |
table.select('tr.dc-table-group').remove(); | |
}); | |
d3.selectAll('a#all').on('click', function() { | |
dc.filterAll(); | |
dc.renderAll(); | |
}); | |
d3.selectAll('a#year').on('click', function() { | |
yearChart.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#month').on('click', function() { | |
monthChart.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#admin1_chart').on('click', function() { | |
admin1Chart.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#admin2_chart').on('click', function() { | |
admin2Chart.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#category').on('click', function() { | |
categoryChart.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#admin1_map').on('click', function() { | |
admin1Map.filterAll(); | |
dc.redrawAll(); | |
}); | |
d3.selectAll('a#admin2_map').on('click', function() { | |
admin2Map.filterAll(); | |
dc.redrawAll(); | |
}); | |
dc.renderAll(); | |
// d3.select(self.frameElement).style("height", height + "px"); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* main.css: Add and override styles */ | |
.dc-data-count small { | |
font-size: 16px; | |
} | |
.container-fluid { | |
padding-left: 40px; | |
padding-right: 40px; | |
} | |
.pie-chart { | |
height: 150px; | |
} | |
.dc-chart .axis text{ | |
font-size: 12px; | |
} | |
text { | |
font-size: 16px; | |
} | |
// #map { | |
// height: 150px; | |
// } | |
#control-row { | |
padding-bottom: 20px; | |
} | |
a { cursor: pointer } | |
.dc-chart g.row text { | |
fill: black; | |
} | |
/*override dc.css*/ | |
.dc-chart g.row rect { | |
opacity: 0.6; | |
} | |
.dc-chart g.mdg_adm1 path { | |
stroke: white | |
} | |
.dc-chart g.mdg_adm2 path { | |
stroke: white | |
} | |
// div.tooltip { | |
// position: absolute; | |
// text-align: center; | |
// width: 60px; | |
// height: 28px; | |
// padding: 2px; | |
// font: 12px sans-serif; | |
// background: lightsteelblue; | |
// border: 0px; | |
// border-radius: 8px; | |
// pointer-events: none; | |
// } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
updated link to source data