|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min.js"></script> |
|
<style> |
|
body { |
|
font-family: futura; |
|
} |
|
h2.title { |
|
color: black; |
|
text-align: center; |
|
} |
|
.axis { |
|
font-family: arial; |
|
font-size: 0.7em; |
|
} |
|
text { |
|
fill: black; |
|
stroke: none; |
|
} |
|
.label { |
|
font-size: 2em; |
|
} |
|
path { |
|
fill: none; |
|
stroke: black; |
|
stroke-width: 2px; |
|
} |
|
.tick { |
|
fill: none; |
|
stroke: black; |
|
} |
|
.bar { |
|
opacity: 0.9; |
|
stroke: none; |
|
fill: steelblue; |
|
} |
|
</style> |
|
|
|
<script type="text/javascript"> |
|
// https://github.com/mbostock/d3/wiki/Time-Formatting |
|
format = d3.time.format("%Y-%m-%d"); |
|
function draw(data) { |
|
"use strict"; |
|
debugger; |
|
// set margins according to Mike Bostock's margin conventions |
|
// http://bl.ocks.org/mbostock/3019563 |
|
|
|
var margin = {top: 25, right: 25, bottom: 100, left: 75}; |
|
|
|
// set height and width of chart |
|
var width = 960 - margin.left - margin.right, |
|
height = 500 - margin.top - margin.bottom; |
|
var barPadding = 10; |
|
// specify the radius of our circles and the |
|
// column we want to plot |
|
var field = 'SANF806PCPI'; |
|
|
|
// Append the title for the graph |
|
d3.select("body") |
|
.append("h2") |
|
.text("Per Capita Personal Income in San Francisco-Oakland-Fremont, CA (MSA)") |
|
.attr('class', 'title'); |
|
// append the SVG tag with height and width to accommodate for margins |
|
var svg = d3.select("body") |
|
.append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.append('g') |
|
.attr('class','chart') |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
// remove missing values |
|
data = data.filter(function(d) { |
|
return d[field]; |
|
}); |
|
// bind our data to svg rects for the bar plot |
|
svg.selectAll(".bar") |
|
.data(data) |
|
.enter() |
|
.append("rect") |
|
.attr('class', 'bar') |
|
// maximum price for rent |
|
var max_y = d3.max(data, function(d) { |
|
return +d[field]; |
|
}); |
|
// get min/max dates |
|
var time_extent = d3.extent(data, function(d){ |
|
return format.parse(d['observation_date']); |
|
}); |
|
// Create x-axis scale mapping dates -> pixels |
|
var time_scale = d3.time.scale() |
|
.range([0, width]) |
|
.domain(time_extent); |
|
// Create y-axis scale mapping price -> pixels |
|
var measure_scale = d3.scale.linear() |
|
.range([height, 0]) |
|
.domain([0, max_y]); |
|
// Create D3 axis object from time_scale for the x-axis |
|
var time_axis = d3.svg.axis() |
|
.scale(time_scale) |
|
.tickFormat(d3.time.format("%Y")); |
|
// Create D3 axis object from measure_scale for the y-axis |
|
var measure_axis = d3.svg.axis() |
|
.scale(measure_scale) |
|
.orient("left"); |
|
// Append SVG to page corresponding to the D3 x-axis |
|
svg.append('g') |
|
.attr('class', 'x axis') |
|
.attr('transform', "translate(0," + height + ")") |
|
.call(time_axis); |
|
// Append SVG to page corresponding to the D3 y-axis |
|
svg.append('g') |
|
.attr('class', 'y axis') |
|
.call(measure_axis); |
|
// add label to y-axis |
|
var y_label = d3.select(".y.axis") |
|
.append("text") |
|
.attr('class', 'label') |
|
.text("Income (Dollars)") |
|
.style('font-size', '1.2em') |
|
.attr("transform", "rotate(-90)"); |
|
|
|
// center y axis label |
|
y_label.attr("x", -(height / 2)).attr('y', -50) |
|
.style("text-anchor", "middle"); |
|
|
|
// based on the data bound to each svg rect, |
|
// change its x, y, width, height accordingly |
|
d3.selectAll('.bar') |
|
.attr('x', function(d) { |
|
return time_scale(format.parse(d['observation_date'])); |
|
}) |
|
.attr('width', function(d) { |
|
return width / data.length - barPadding; |
|
}) |
|
.attr('y', function(d) { |
|
return measure_scale(+d[field]); |
|
}) |
|
.attr('height', function(d) { |
|
return height - measure_scale(+d[field]); |
|
}); |
|
console.log(data) |
|
}; |
|
</script> |
|
</head> |
|
<body> |
|
<script type="text/javascript"> |
|
// load our data file asynchronously and pass the data |
|
// to the draw function once it is loaded. |
|
d3.csv("per_capita_income.csv", draw); |
|
</script> |
|
</body> |
|
</html> |