Skip to content

Instantly share code, notes, and snippets.

@slnader
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slnader/9452976 to your computer and use it in GitHub Desktop.
Save slnader/9452976 to your computer and use it in GitHub Desktop.
Positive and Negative Values Bar Chart

Barchart with positive and negative values and a dropdown to toggle between metrics. Use the dropdown menu to toggle between trends in demand rides and bus rides between 2010 and 2011, for cities with metro areas over 1 million people. Data source: Bus ride and demand ride transportation statistics from the American Public Transportation Association, 2010-2011.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Positive and Negative Value Bar Chart</title>
<link href="transport.css" rel="stylesheet">
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<div class ="description">
<table>
<tr>
<td>
<select>
<option id="item" value="demand">Demand Ride Percent Change</option>
<option id="item" value="bus">Bus Ride Percent Change</option>
</select>
</td>
</tr>
<tr>
<td>
<ul>
<li><input type="checkbox" class="checkbox" name="check" value="sort"> </li>
<li>Sort by percent change</li>
</ul>
</div>
</td>
</tr>
</table>
</div>
<br>
<div id="chart-container"></div>
<script type="text/javascript" src="transport.js"></script>
</div> <!--description-->
</body>
</html>
body{
font-family: sans-serif;
}
.positive{
fill: lightsteelblue;
fill-opacity: 0.9;
}
.negative{
fill: darkred;
fill-opacity: 0.9;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 10px;
}
div.tooltip {
position: absolute;
text-align: center;
vertical-align: middle;
width: 150px;
height: 50px;
padding: 5px;
color: #000000;
font-size: 12px;
background: #FFF;
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
border: 2px;
border-radius: 8px;
pointer-events: none;
}
li{
overflow:hidden;
display: inline-block;
}
ul{
padding-left: 0;
padding-right: 0;
}
#chart-container{
float:left;
}
var dataset;
//Define bar chart function
function barChart(dataset){
//Set width and height as fixed variables
var w = 520;
var h = 500;
var padding = 25;
//Scale function for axes and radius
var yScale = d3.scale.linear()
.domain(d3.extent(dataset, function(d){return d.dr_change;}))
.range([w+padding,padding]);
var xScale = d3.scale.ordinal()
.domain(dataset.map(function(d){ return d.name;}))
.rangeRoundBands([padding,h+padding],.5);
//To format axis as a percent
var formatPercent = d3.format("%1");
//Create y axis
var yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(5).tickFormat(formatPercent);
//Define key function
var key = function(d){return d.name};
//Define tooltip for hover-over info windows
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//Create svg element
var svg = d3.select("#chart-container").append("svg")
.attr("width", w).attr("height", h)
.attr("id", "chart")
.attr("viewBox", "0 0 "+w+ " "+h)
.attr("preserveAspectRatio", "xMinYMin");
//Resizing function to maintain aspect ratio (uses jquery)
var aspect = w / h;
var chart = $("#chart");
$(window).on("resize", function() {
var targetWidth = $("body").width();
if(targetWidth<w){
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
}
else{
chart.attr("width", w);
chart.attr("height", w / aspect);
}
});
//Initialize state of chart according to drop down menu
var state = d3.selectAll("option");
//Create barchart
svg.selectAll("rect")
.data(dataset, key)
.enter()
.append("rect")
.attr("class", function(d){return d.dr_change < 0 ? "negative" : "positive";})
.attr({
x: function(d){
return xScale(d.name);
},
y: function(d){
return yScale(Math.max(0, d.dr_change));
},
width: xScale.rangeBand(),
height: function(d){
return Math.abs(yScale(d.dr_change) - yScale(0));
}
})
.on('mouseover', function(d){
d3.select(this)
.style("opacity", 0.2)
.style("stroke", "black")
var info = div
.style("opacity", 1)
.style("left", (d3.event.pageX+10) + "px")
.style("top", (d3.event.pageY-30) + "px")
.text(d.name);
if(state[0][0].selected){
info.append("p")
.text(formatPercent(d.dr_change));
}
else if(state[0][1].selected){
info.append("p")
.text(formatPercent(d.bus_change));
}
})
.on('mouseout', function(d){
d3.select(this)
.style({'stroke-opacity':0.5,'stroke':'#a8a8a8'})
.style("opacity",1);
div
.style("opacity", 0);
});
//Add y-axis
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(40,0)")
.call(yAxis);
//Sort data when sort is checked
d3.selectAll(".checkbox").
on("change", function(){
var x0 = xScale.domain(dataset.sort(sortChoice())
.map(function(d){return d.name}))
.copy();
var transition = svg.transition().duration(750);
var delay = function(d, i){return i*10;};
transition.selectAll("rect")
.delay(delay)
.attr("x", function(d){return x0(d.name);});
})
//Function to sort data when sort box is checked
function sortChoice(){
var state = d3.selectAll("option");
var sort = d3.selectAll(".checkbox");
if(sort[0][0].checked && state[0][0].selected){
var out = function(a,b){return b.dr_change - a.dr_change;}
return out;
}
else if(sort[0][0].checked && state[0][1].selected){
var out = function(a,b){return b.bus_change - a.bus_change;}
return out;
}
else{
var out = function(a,b){return d3.ascending(a.name, b.name);}
return out;
}
};
//Change data to correct values on input change
d3.selectAll("select").
on("change", function() {
var value= this.value;
if(value=="bus"){
var x_value = function(d){return d.bus_change;};
var color = function(d){return d.bus_change < 0 ? "negative" : "positive";};
var y_value = function(d){
return yScale(Math.max(0, d.bus_change));
};
var height_value = function(d){
return Math.abs(yScale(d.bus_change) - yScale(0));
};
}
else if(value=="demand"){
var x_value = function(d){return d.dr_change;};
var color = function(d){return d.dr_change < 0 ? "negative" : "positive";};
var y_value = function(d){
return yScale(Math.max(0, d.dr_change));
};
var height_value = function(d){
return Math.abs(yScale(d.dr_change) - yScale(0));
};
}
//Update y scale
yScale.domain(d3.extent(dataset, x_value));
//Update with correct data
var rect = svg.selectAll("rect").data(dataset, key);
rect.exit().remove();
//Transition chart to new data
rect
.transition()
.duration(2000)
.ease("linear")
.each("start", function(){
d3.select(this)
.attr("width", "0.2")
.attr("class", color)
})
.attr({
x: function(d){
return xScale(d.name);
},
y: y_value,
width: xScale.rangeBand(),
height: height_value
});
//Update y-axis
svg.select(".y.axis")
.transition()
.duration(1000)
.ease("linear")
.call(yAxis);
});
};
//Load data and call bar chart function
d3.csv("transportation_change_2012-2013_small.csv", function(error,data){
if(error){
console.log(error);
}
else{
data.forEach(function(d) {
d.dr_change = parseFloat(d.dr_change);
d.bus_change = parseFloat(d.bus_change);
});
dataset=data;
barChart(dataset);
}
});
name dr_trips_2013 dr_trips_2012 dr_change bus_trips_2013 bus_trips_2012 bus_change
1 Atlanta, GA 636550 623600 0.02 69855.83 77839.6 -0.1
2 Austin, TX 647000 666100 -0.03 33486.97 34814.4 -0.04
3 Baltimore, MD 1663380 1488900 0.12 73568.35 74651.8 -0.01
4 Boston, MA 2862660 2597000 0.1 116981.5 114954.8 0.02
5 Charlotte, NC 229150 234000 -0.02 22152.3 20361 0.09
6 Chicago, IL 4810700 4171500 0.15 342297.97 336764 0.02
7 Cincinnati, OH 425230 421100 0.01 22394.77 22322.1 0
8 Cleveland, OH 800340 779900 0.03 37539.63 36386.2 0.03
9 Columbus, OH 259880 238300 0.09 18764.05 17034.9 0.1
10 Dallas, TX 1980670 1718600 0.15 43611.26 44240.3 -0.01
11 Denver, CO 1135400 1172300 -0.03 75954.77 76168.2 0
12 Detroit, MI 1038010 856300 0.21 46275.69 47995.2 -0.04
13 Houston, TX 1831840 1719900 0.07 66451.03 66663.1 0
14 Indianapolis, IN 257370 250200 0.03 9254.94 8527.9 0.09
15 Jacksonville, FL 383740 369600 0.04 11719.91 10757.5 0.09
16 Kansas City, MO 602830 566200 0.06 16147.32 15101.9 0.07
17 Las Vegas, NV 1209120 1031800 0.17 55476.97 56382.3 -0.02
18 Los Angeles, CA 7006510 7214300 -0.03 541955.05 554560.1 -0.02
19 Memphis, TN 243520 236000 0.03 9287.21 10114 -0.08
20 Miami, FL 3192860 3214900 -0.01 125753.27 119750.1 0.05
21 Milwaukee, WI 1082510 1304300 -0.17 45358.16 43595.4 0.04
22 Minneapolis, MN 1983150 1917600 0.03 80638.03 78435.4 0.03
23 New York, NY 8610840 8309000 0.04 1190395.01 1230428.6 -0.03
24 Orlando, FL 821170 749600 0.1 26996.16 24780.7 0.09
25 Philadelphia, PA 2982250 2964200 0.01 193134.74 187333.1 0.03
26 Phoenix, AZ 857260 926600 -0.07 53845.28 54315.8 -0.01
27 Pittsburgh, PA 1835180 1758500 0.04 55509.78 57697 -0.04
28 Portland, OR 1289170 1307800 -0.01 65298.29 67114.8 -0.03
29 Providence, RI 866570 836900 0.04 20197.71 20298.5 0
30 Riverside, CA 1003760 1000300 0 22500.36 22067.3 0.02
31 Sacramento, CA 449710 382500 0.18 16613.57 21295.5 -0.22
32 Salt Lake City, UT 565810 509700 0.11 21560.36 21716.9 -0.01
33 San Antonio, TX 1051100 1054200 0 44157.54 41323.1 0.07
34 San Diego, CA 579110 548600 0.06 60062 59705.2 0.01
35 San Francisco, CA 2153120 2245600 -0.04 170242.66 177021.6 -0.04
36 San Jose, CA 824810 930200 -0.11 31652.43 32210.8 -0.02
37 San Juan, PR 114250 117000 -0.02 11576.12 14236 -0.19
38 Seattle, WA 2014470 2035600 -0.01 109946.68 126658.8 -0.13
39 St. Louis, MO 652120 635700 0.03 28347.54 26258.3 0.08
40 Tampa, FL 496000 457800 0.08 28206.05 26256.8 0.07
41 Virginia Beach, VA 346200 313400 0.1 15724.6 17843.2 -0.12
42 Washington, DC 2947900 2977400 -0.01 184024.56 181877.3 0.01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment