Skip to content

Instantly share code, notes, and snippets.

@alexmacy
Last active May 16, 2019 09:12
Show Gist options
  • Save alexmacy/c0302e4d78cebc193840 to your computer and use it in GitHub Desktop.
Save alexmacy/c0302e4d78cebc193840 to your computer and use it in GitHub Desktop.
Past Presidents

This dashboard was made for testing a couple different visualizations. Mainly a sortable data table and a stacked single-line row charts. It displays data about U.S Presidents, their party affiliations, duration in office, etc.

Pie charts are very convenient, but are not ideal for accurately displaying data - not to mention have a steadily decreasing amount of fans, so I wanted something that would easliy display comparable percentages of a whole, while not requiring less space than is needed for a histogram.

That brought me to making a stacked row chart that falls somewhere in the middle of the two. To do this, I repurposed a bar chart, gave all the bars the same height, and adjusting their width and placement based upon their percentage of the whole. The top row chart resizes based on the time period selected, and the bars on both charts fade when either outside of the selected time period or if their party is not selected.

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" media="screen" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script src="presidents.js"></script>
<style>
body {
font: 15px sans-serif;
margin: 2% 1% 0 1%;
}
.chart text {
fill: white;
text-anchor: end;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
fill-opacity: .125;
shape-rendering: crispEdges;
}
.resize path {
fill: #666;
fill-opacity: .2;
stroke: #000;
stroke-width: 1.5px;
}
rect {
stroke: white;
stroke-width: .25px;
}
.deselected {
opacity: .125
}
th {
background: url(http://tablesorter.com/themes/blue/bg.gif) no-repeat 99%;
cursor:pointer
}
</style>
</head>
<body>
<div style="width:75%;float:left" id="charts-div">
<span id="chart"><strong style="margin-left:10px">Party Representation:</strong><svg id="partyRowChart" class="chart"></svg></span>
<br>
<strong style="margin-left: 10px;margin-top: 10px">Presidential Timeline:</strong>
<span id="presRowChart"></span>
<div id="numbers" style="margin-top: 10px;margin-left: 10px">
<span style="float:left">Presidents entering office between <strong><span id="start-year">1789</span> </strong></span>
<span>&nbspand <strong><span id="end-year">2016</span></strong></span>
<span>: <strong><span id="count">44</span> of 44</strong></span>
</div>
<table id="table-div" class="table table-hover" style="margin-top: 20px;margin-left:10px">
<thead>
<tr>
<th class='col-sm-2' id="num_col" onclick="sortList(byNumber, num_col)">Number</th>
<th class='col-sm-4' id="pres_col" onclick="sortList(byName, pres_col)">President</th>
<th class='col-sm-3' id="party_col" onclick="sortList(byParty, party_col)">Party</th>
<th class='col-sm-2' id="enter_col" onclick="sortList(byNumber, enter_col)">In Office</th>
<th class='col-sm-1' id="years_col" onclick="sortList(byYearsInOffice, years_col)">Years</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id="color-div" style="width:25%;float:right">
<ul style="list-style-type:none;">
<li class="checkbox"><label><input type="checkbox" onchange="checkAll(this)"><b style="color: black">Select All</b></label></li>
</ul>
<ul style="list-style-type:none" id="party-list">
</ul>
</div>
</body>
<script>
//some global variables
var filter = [],
listDimension,
brush,
width = document.getElementById('table-div').getBoundingClientRect().width,
height = 70,
barHeight = 40,
sortBy = 'desc',
presList;
//x-axis for presRowChart & brush-slider
var xYear = d3.scale.linear()
.domain([1789,2017])
.range([0,width - 20])
//define the skeletons for the charts and brush-slider
var partyRowChart = d3.select('#partyRowChart')
.attr('width', width - 20)
.attr('height', barHeight)
.attr('style', 'margin-left:10px');
var presRowSVG = d3.select('#presRowChart').append('svg')
.attr('width', width)
.attr('height', 90);
var presRowChart = presRowSVG.append('g')
.attr('width', width - 20)
.attr('height', 40)
.attr('transform', 'translate(10,0)')
//set colors to political parties and create and ordinal scale
var parties = ['Democratic', 'Democratic-Republican', 'Federalist', 'No-Party', 'Republican', 'Whig'],
colorSet = ['#0f5495', '#0f750f', '#8a5724', '#757575', '#db0f0f', '#ff950e'];
var colors = d3.scale.ordinal().domain(parties).range(colorSet);
//pare the dates down to just the year
presidents.forEach(d => {
d.took_office = +d.took_office.split("-")[0];
d.left_office = +d.left_office.split("-")[0];
d.years_in_office = +d.left_office - +d.took_office;
})
//load the crossfilter
var cf = crossfilter(presidents);
var byParty = cf.dimension( d => d.party);
var byNumber = cf.dimension( d => d.number);
var byName = cf.dimension( d => d.president);
var byTookOffice = cf.dimension( d => d.took_office);
var byYearsInOffice = cf.dimension( d => d.years_in_office);
//create the party list for the right side
d3.select('#party-list').selectAll('li')
.data(parties)
.enter().append('li')
.attr('class', 'checkbox')
.attr('id',d => d + '-box')
.append('label')
.html((d) =>'<input type="checkbox" id="' + d + '_Box"><b style="color:' + colors(d) + '">' + d + '</b>')
.on('click', d => filterByParty() );
/////////loading visualization elements
function loadPartyBar() {
d3.select('#partyRowChart').selectAll('g').remove();
d3.select('#count').html(byParty.top(Infinity).length);
var data = byParty.group().all();
var total = d3.sum(data, d => d.value);
var x = d3.scale.linear()
.domain([0, total])
.range([0, width - 20]);
var bar = partyRowChart.selectAll('g')
.data(data)
.enter().append('g')
.attr('transform', (d,i) => 'translate(' + x(total - d3.sum(data.slice(i), n => n.value)) + ',0)')
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.key))
.on("mousemove", d => tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px"))
.on("mouseout", d => tooltip.style("visibility", "hidden"));
bar.append('rect')
.attr('width', d => x(d.value))
.attr('height', barHeight - 1)
.attr('fill', d => colors(d.key))
.classed('deselected', d => filter.indexOf(d.key) < 0 )
bar.append('text')
.attr('x', d => x(d.value) - 3)
.attr('y', barHeight / 2)
.attr('dy', '.35em')
.text( d => {if (d.value != 0) { return d.value; }})
};
function loadPresBar() {
var bar = presRowChart.selectAll('g')
.data(byNumber.bottom(Infinity))
.enter().append('g')
.attr("transform", d => "translate(" + xYear(+d.took_office) + ",0)")
.on("mouseover", d => tooltip.style("visibility", "visible")
.html(d.president + " : " + d.took_office + ' - ' + d.left_office))
.on("mousemove", d => tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px"))
.on("mouseout", d => tooltip.style("visibility", "hidden")
.html(''));
bar.append("rect")
.attr("height", 40)
.attr("width", d => xYear(d.left_office) - xYear(d.took_office))
.attr('fill', d => colors(d.party))
.attr('id', d => 'bar_' + d.took_office)
.attr('class', d => 'presBar ' + d.party)
presRowChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + 40 + ")")
.call(d3.svg.axis()
.scale(xYear)
.orient("bottom")
.ticks(5)
.tickFormat(d3.format("")));
}
function loadSlider() {
brush = d3.svg.brush()
.x(xYear)
.extent([1829, 1901])
.on('brush', d => brushed())
var brushg = presRowSVG.append("g")
.attr("class", "brush")
.attr("transform", "translate(10," + 40 + ")")
.call(brush);
function handlePath(d) {
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 3;
return "M" + (.5 * x) + "," + y
+ "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
+ "V" + (2 * y - 6)
+ "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
+ "Z"
+ "M" + (3.25 * x) + "," + (y + 8)
+ "V" + (2 * y - 8);
}
brushg.selectAll(".resize").append("path").attr("d", handlePath);
brushg.selectAll("rect").attr("height", 48);
brushed();
}
function loadPresList() {
var listHTML = "";
presList = (sortBy == 'desc') ? listDimension.bottom(Infinity) : listDimension.top(Infinity);
for (let i of presList) {
listHTML +='<tr id="list-line' + i.number + '" class="' + i.party + '_row">' +
'<td>' + i.number + '</td>' +
'<td>' + i.president + '</td>' +
'<td>' + i.party + '</td>' +
'<td>' + i.took_office + ' - ' + i.left_office + '</td>' +
'<td>' + i.years_in_office + '</td>' +
'</tr>';
};
d3.select('tbody').html(listHTML);
}
function sortList(dimensionVal, col) {
dimensionVal != listDimension ? listDimension = dimensionVal : sortBy == 'desc' ? sortBy = 'asc' : sortBy = 'desc';
loadPresList()
}
////////////////filtering functions
function brushed() {
var brushYears = brush.empty() ? [1789,2017] : brush.extent().map(Math.round)
byTookOffice.filter([brushYears[0],brushYears[1]]);
d3.select('#start-year').html(brushYears[0]);
d3.select('#end-year').html(brushYears[1]);
filterByParty();
}
function checkAll(val) {
var boxes = d3.selectAll('input')[0];
val.checked ? boxes.forEach( d => d.checked = true) : boxes.forEach( d => d.checked = false)
filterByParty();
}
function filterByParty() {
//reset the filter
filter = [];
for (let i of parties) {
if (document.getElementById(i + "_Box").checked) { filter.push(i) };
}
//if no boxes have been checked, push all the parties to the filter
if (filter.length == 0) { filter = parties; }
//filter the dimension
byParty.filter( d => filter.indexOf(d) > -1);
//change opacity of president bars based on if their party is filtered and they don't fall within the time range
d3.select('#presRowChart').selectAll('.presBar')
.classed('deselected', d => byTookOffice.top(Infinity).indexOf(d) < 0);
loadPartyBar();
loadPresList();
}
function loadAll() {
presList = byNumber.bottom(Infinity)
listDimension = byNumber
loadPartyBar();
loadPresList();
loadPresBar();
}
loadAll();
loadSlider();
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background-color", "black")
.style("color", "white")
.style("padding", "5px")
.style("border-radius", "5px")
</script>
//list of presidents, year data and affiliated political party
var presidents = [
{"number":1,"president":"George Washington","birth_year":1732,"death_year":1799,"took_office":"1789-04-30","left_office":"1797-03-04","party":"No-Party"},
{"number":2,"president":"John Adams","birth_year":1735,"death_year":1826,"took_office":"1797-03-04","left_office":"1801-03-04","party":"Federalist"},
{"number":3,"president":"Thomas Jefferson","birth_year":1743,"death_year":1826,"took_office":"1801-03-04","left_office":"1809-03-04","party":"Democratic-Republican"},
{"number":4,"president":"James Madison","birth_year":1751,"death_year":1836,"took_office":"1809-03-04","left_office":"1817-03-04","party":"Democratic-Republican"},
{"number":5,"president":"James Monroe","birth_year":1758,"death_year":1831,"took_office":"1817-03-04","left_office":"1825-03-04","party":"Democratic-Republican"},
{"number":6,"president":"John Quincy Adams","birth_year":1767,"death_year":1848,"took_office":"1825-03-04","left_office":"1829-03-04","party":"Democratic-Republican"},
{"number":7,"president":"Andrew Jackson","birth_year":1767,"death_year":1845,"took_office":"1829-03-04","left_office":"1837-03-04","party":"Democratic"},
{"number":8,"president":"Martin Van Buren","birth_year":1782,"death_year":1862,"took_office":"1837-03-04","left_office":"1841-03-04","party":"Democratic"},
{"number":9,"president":"William Henry Harrison","birth_year":1773,"death_year":1841,"took_office":"1841-03-04","left_office":"1841-04-04","party":"Whig"},
{"number":10,"president":"John Tyler","birth_year":1790,"death_year":1862,"took_office":"1841-04-04","left_office":"1845-03-04","party":"Whig"},
{"number":11,"president":"James K. Polk","birth_year":1795,"death_year":1849,"took_office":"1845-03-04","left_office":"1849-03-04","party":"Democratic"},
{"number":12,"president":"Zachary Taylor","birth_year":1784,"death_year":1850,"took_office":"1849-03-04","left_office":"1850-07-09","party":"Whig"},
{"number":13,"president":"Millard Fillmore","birth_year":1800,"death_year":1874,"took_office":"1850-07-09","left_office":"1853-03-04","party":"Whig"},
{"number":14,"president":"Franklin Pierce","birth_year":1804,"death_year":1869,"took_office":"1853-03-04","left_office":"1857-03-04","party":"Democratic"},
{"number":15,"president":"James Buchanan","birth_year":1791,"death_year":1868,"took_office":"1857-03-04","left_office":"1861-03-04","party":"Democratic"},
{"number":16,"president":"Abraham Lincoln","birth_year":1809,"death_year":1865,"took_office":"1861-03-04","left_office":"1865-04-15","party":"Republican"},
{"number":17,"president":"Andrew Johnson","birth_year":1808,"death_year":1875,"took_office":"1865-04-15","left_office":"1869-03-04","party":"Democratic"},
{"number":18,"president":"Ulysses S. Grant","birth_year":1822,"death_year":1885,"took_office":"1869-03-04","left_office":"1877-03-04","party":"Republican"},
{"number":19,"president":"Rutherford B. Hayes","birth_year":1822,"death_year":1893,"took_office":"1877-03-04","left_office":"1881-03-04","party":"Republican"},
{"number":20,"president":"James A. Garfield","birth_year":1831,"death_year":1881,"took_office":"1881-03-04","left_office":"1881-09-19","party":"Republican"},
{"number":21,"president":"Chester A. Arthur","birth_year":1829,"death_year":1886,"took_office":"1881-09-19","left_office":"1885-03-04","party":"Republican"},
{"number":22,"president":"Grover Cleveland","birth_year":1837,"death_year":1908,"took_office":"1885-03-04","left_office":"1889-03-04","party":"Democratic"},
{"number":23,"president":"Benjamin Harrison","birth_year":1833,"death_year":1901,"took_office":"1889-03-04","left_office":"1893-03-04","party":"Republican"},
{"number":24,"president":"Grover Cleveland","birth_year":1837,"death_year":1908,"took_office":"1893-03-04","left_office":"1897-03-04","party":"Democratic"},
{"number":25,"president":"William McKinley","birth_year":1843,"death_year":1901,"took_office":"1897-03-04","left_office":"1901-09-14","party":"Republican"},
{"number":26,"president":"Theodore Roosevelt","birth_year":1858,"death_year":1919,"took_office":"1901-09-14","left_office":"1909-03-04","party":"Republican"},
{"number":27,"president":"William Howard Taft","birth_year":1857,"death_year":1930,"took_office":"1909-03-04","left_office":"1913-03-04","party":"Republican"},
{"number":28,"president":"Woodrow Wilson","birth_year":1856,"death_year":1924,"took_office":"1913-03-04","left_office":"1921-03-04","party":"Democratic"},
{"number":29,"president":"Warren G. Harding","birth_year":1865,"death_year":1923,"took_office":"1921-03-04","left_office":"1923-08-02","party":"Republican"},
{"number":30,"president":"Calvin Coolidge","birth_year":1872,"death_year":1933,"took_office":"1923-08-02","left_office":"1929-03-04","party":"Republican"},
{"number":31,"president":"Herbert Hoover","birth_year":1874,"death_year":1964,"took_office":"1929-03-04","left_office":"1933-03-04","party":"Republican"},
{"number":32,"president":"Franklin D. Roosevelt","birth_year":1882,"death_year":1945,"took_office":"1933-03-04","left_office":"1945-04-12","party":"Democratic"},
{"number":33,"president":"Harry S. Truman","birth_year":1884,"death_year":1972,"took_office":"1945-04-12","left_office":"1953-01-20","party":"Democratic"},
{"number":34,"president":"Dwight D. Eisenhower","birth_year":1890,"death_year":1969,"took_office":"1953-01-20","left_office":"1961-01-20","party":"Republican"},
{"number":35,"president":"John F. Kennedy","birth_year":1917,"death_year":1963,"took_office":"1961-01-20","left_office":"1963-11-22","party":"Democratic"},
{"number":36,"president":"Lyndon B. Johnson","birth_year":1908,"death_year":1973,"took_office":"1963-11-22","left_office":"1969-01-20","party":"Democratic"},
{"number":37,"president":"Richard Nixon","birth_year":1913,"death_year":1994,"took_office":"1969-01-20","left_office":"1974-08-09","party":"Republican"},
{"number":38,"president":"Gerald Ford","birth_year":1913,"death_year":2006,"took_office":"1974-08-09","left_office":"1977-01-20","party":"Republican"},
{"number":39,"president":"Jimmy Carter","birth_year":1924,"death_year":null,"took_office":"1977-01-20","left_office":"1981-01-20","party":"Democratic"},
{"number":40,"president":"Ronald Reagan","birth_year":1911,"death_year":2004,"took_office":"1981-01-20","left_office":"1989-01-20","party":"Republican"},
{"number":41,"president":"George H. W. Bush","birth_year":1924,"death_year":null,"took_office":"1989-01-20","left_office":"1993-01-20","party":"Republican"},
{"number":42,"president":"Bill Clinton","birth_year":1946,"death_year":null,"took_office":"1993-01-20","left_office":"2001-01-20","party":"Democratic"},
{"number":43,"president":"George W. Bush","birth_year":1946,"death_year":null,"took_office":"2001-01-20","left_office":"2009-01-20","party":"Republican"},
{"number":44,"president":"Barack Obama","birth_year":1961,"death_year":null,"took_office":"2009-01-20","left_office":"2017-01-20","party":"Democratic"}
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment