Skip to content

Instantly share code, notes, and snippets.

@jsanch
Created August 3, 2016 19:24
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 jsanch/0f0ad4ea1a916eef191a2d98cd1899c1 to your computer and use it in GitHub Desktop.
Save jsanch/0f0ad4ea1a916eef191a2d98cd1899c1 to your computer and use it in GitHub Desktop.
<link rel="stylesheet" href="https://marks.github.io/cdc-indicator-explorer/css/nhis-early-release.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link href="https://pingendo.github.io/pingendo-bootstrap/themes/default/bootstrap.css" rel="stylesheet" type="text/css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<!-- base dependencies (bootstrap, font-awesome) -->
<!-- visualization dependencies (plotly) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/socrata/soda-js/master/lib/soda-js.bundle.js"></script>
<div class="section" style='padding-top:0px;'>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="page-header" style="margin-top:20px">
<h1 style="margin-top:0px;">NHIS Early Release Explorer <small>alpha</small></h1></div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="well">
<form id="form" role="form">
<div class="form-group">
<label for="topicDropdown">Select a topic:</label>
<select class="form-control" id="topicDropdown">
<option>Serious psychological distress</option>
<option selected>Diagnosed diabetes </option>
<option>Asthma</option>
</select>
</div>
<button type="submit" class="btn btn-default for-accessibility">Submit</button>
</form>
</div>
<div class="">
<hr />
<h2>About this tool</h2>
<p>This tool uses the <a href='https://cdc-nchs.demo.socrata.com/dataset/KHI-Combined-Data-Figures-14-1-14-2-14-3-/y73x-njsu' target='blank'>NHIS</a> dataset from <code>cdc-nchs.demo. socrata.com</code>. Visit the dataset page to explore the data in your browser, create custom visualizations, and export the data as CSV, JSON, XML, and/or access it via API.
<br /><br />
<p><strong>Data URL</strong></p>
<code id="query-url"></code>
<br /><br />
<p><strong>Built With</strong></p>
<p>This tool uses open source technology and the Socrata open data platform. The following components of the tool are licensed under the <a href='https://en.wikipedia.org/wiki/MIT_License'>MIT license</a>: Twitter Bootstrap, jQuery, Font Awesome, Lodash, soda-js.</p>
</div>
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-12">
<h2 id='visualizations-header'>Loading...</h2>
</div>
</div>
<div class="row">
<div id="visualizations"></div>
</div>
</div>
</div>
</div>
</div>
<!-- <script src="https://marks.github.io/cdc-indicator-explorer/js/nhis-early-release.js"></script> -->
<script>
$(document).ready(function() {
/* do these things when ready() */
sodaConsumer = new soda.Consumer('cdc-nchs.demo.socrata.com');
processInput() // run visualization on load
/* event handlers */
$("#form select").change(function(event) {
event.preventDefault();
formSubmitted()
});
$("#form").submit(function(event) { // needed for accessibility reasons
event.preventDefault();
formSubmitted()
});
});
/* helper methods */
function formSubmitted(){
$("#visualizations").html("")
processInput()
}
function processInput() {
params = {
topic: $("#form #topicDropdown").val(),
}
// set header text
$("h2#visualizations-header").text(params.topic)
// get data from socrata API
var sodaQuery = sodaConsumer.query()
.withDataset('xt9n-yu9c')
.where({
'topic': params.topic,
})
.select('*')
.order('figure_id asc, metric asc, gender desc, year asc')
// .where('locationabbr IN ("US","' + params.state + '")')
// .where('year IS NOT NULL')
var queryURL = decodeURIComponent(sodaQuery.getURL())
$("code#query-url").text(queryURL)
sodaQuery
.getRows()
.on('success', handleData)
.on('error', function(error) {
console.error(error);
});
}
function handleData(rows) {
console.log(rows)
/* for each figure, create a chart */
var rowsGroupedByFigure = _.groupBy(rows,'figure_id')
_.each(rowsGroupedByFigure, function(rowsForFigure,figureId){
var figure = rowsForFigure[0].figure
var figureType = figureId.split(".")[1]
var figureSlug = slugify(figureId+"--"+figure)
/* ------------------------------------------------------------------------ */
var trendChartHTML = plotlyVisualizationPanelTemplate({
slug:figureSlug,
title:"<small>Figure "+figureId+"</small><br />"+figure,
css_class:"chart",
caption:"<strong>Cras justo odio:</strong> Dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit."
})
$("#visualizations").append(trendChartHTML)
console.log(rowsForFigure)
var plotlyLayout = {
barmode: 'group',
yaxis: {title: undefined},
xaxis: {title: undefined},
bargap:0.2,
bargroupgap:0.05
}
if(figureType == "1") {
var data = _.map(_.groupBy(rowsForFigure, 'metric'), function(rowsForChart, metric){
return {
x: _.map(rowsForChart,'year'),
y: _.map(rowsForChart,'value'),
name: metric,
marker: {
color: seriesNameToColor(metric)
},
error_y: {
type: 'data',
symmetric: false,
array: _.map(rowsForChart, function(i){return parseFloat(i.confidence_interval_upper_bound) - parseFloat(i.value)}),
arrayminus: _.map(rowsForChart, function(i){return parseFloat(i.value)-parseFloat(i.confidence_interval_lower_bound)}),
visible: true
},
type: 'bar',
}
})
plotlyLayout.yaxis.title = "Percent"
plotlyLayout.xaxis.title = "Year"
// accordion revealing data table
var rowsByYear = _.groupBy(rowsForFigure, 'year')
var accordionAndTableHtml = datatableByYearAccordionTemplate({rowsByYear: rowsByYear})
$("."+figureSlug+" .data-table").html(accordionAndTableHtml)
} else if(figureType == "2") {
var data = _.map(_.groupBy(rowsForFigure, 'gender'), function(rowsForChart, metric){
return {
x: _.map(rowsForChart,'age_group'),
y: _.map(rowsForChart,'value'),
name: metric,
marker: {
color: seriesNameToColor(metric)
},
error_y: {
type: 'data',
symmetric: false,
array: _.map(rowsForChart, function(i){return parseFloat(i.confidence_interval_upper_bound) - parseFloat(i.value)}),
arrayminus: _.map(rowsForChart, function(i){return parseFloat(i.value)-parseFloat(i.confidence_interval_lower_bound)}),
visible: true
},
type: 'bar',
}
})
plotlyLayout.yaxis.title = "Percent"
plotlyLayout.xaxis.title = "Age Group (years)"
} else if(figureType == "3") {
var data = _.map(_.groupBy(rowsForFigure, 'metric'), function(rowsForChart, metric){
return {
x: _.map(rowsForChart,'race_ethnicity'),
y: _.map(rowsForChart,'value'),
name: metric,
marker: {
color: seriesNameToColor(metric)
},
error_y: {
type: 'data',
symmetric: false,
array: _.map(rowsForChart, function(i){return parseFloat(i.confidence_interval_upper_bound) - parseFloat(i.value)}),
arrayminus: _.map(rowsForChart, function(i){return parseFloat(i.value)-parseFloat(i.confidence_interval_lower_bound)}),
visible: true
},
type: 'bar',
}
})
plotlyLayout.yaxis.title = "Percent"
plotlyLayout.xaxis.title = "Race/Ethnicity"
} else {
var data = []
}
Plotly.newPlot(figureSlug, data, plotlyLayout, {displaylogo: false, displayModeBar: false});
})
}
var plotlyVisualizationPanelTemplate = _.template('<div class="col-md-12 <%= slug %>"> \
<div class="panel panel-default"> \
<div class="panel-body"> \
<h3><%= title %></h3> \
<div class="<%= css_class %>" id="<%= slug %>"></div> \
<div class="data-table"></div> \
<p><%= caption %></p> \
</div>\
</div> \
</div>')
var datatableByYearAccordionTemplate = _.template(' \
<div class="panel-group"> \
<div class="panel panel-default"> \
<div class="panel-heading"> \
<h4 class="panel-title"> \
<a data-toggle="collapse" href="#collapse1">View Data Table</a> \
</h4> \
</div> \
<div id="collapse1" class="panel-collapse collapse"> \
<div class="panel-body"> \
<table> \
<tr> \
<th class="tg-031e">Year</th> \
<th class="tg-s6z2">Crude[1] percent<br>(95% confidence interval)</th> \
<th class="tg-s6z2">Age-adjusted[2] percent<br>(95% confidence interval)</th> \
</tr> \
<% _.each(rowsByYear, function(metricsForYear, year){ %> \
<tr><td class="tg-031e"><%= year %></td> \
<% _.each(metricsForYear, function(row){ %> \
<td class="tg-s6z2"><%= rowToValueWithInterval(row) %></td> \
<% }) %> \
</tr> \
<% }) %> \
</table> \
</div> \
<div class="panel-footer">Data Source: CDC/NCHS, National Health Interview Survey</div> \
</div> \
</div> \
</div>')
function seriesNameToColor(name) {
switch(name) {
case "Crude[1] percent":
return "#69318f"
case "Age-adjusted[2] percent":
return "#609639"
case "Total":
return "#609639"
case "Male":
return "#a388bc"
case "Female":
return "#69318f"
default:
return "#a388bc"
}
}
function rowToValueWithInterval(row){
return row.value+" ("+row.confidence_interval_lower_bound+"-"+row.confidence_interval_upper_bound+")"
}
function slugify(text){
return text.toString().toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
.replace(/\-\-+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, ''); // Trim - from end of text
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment