These are the materials for my workshop on creating interactive data visualizations with D3! We will be using the following two tools to works through these exercises:
And please do not hesitate to reach out to me directly via email at jondinu@gmail.com or over twitter @clearspandex
Throughout this workshop, you will learn how to make an interactive map of AirBnB listings in SF to better understand the companies impact on the city.
The data comes from Inside AirBnB and it is available below under a Creative Commons CC0 1.0 Universal (CC0 1.0) "Public Domain Dedication" license.
Inside AirBnB is an independent, non-commercial set of tools and data that allows you to explore how Airbnb is really being used in cities around the world.
Github repo: https://github.com/Jay-Oh-eN/interactive-data-viz
Archival event link: Open Data Science Conference SF 2015
forked from Jay-Oh-eN's block: Civic Impact through Data Visualization: Exercise 1
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.8/d3.min.js"></script>
<style>
circle {
opacity: 0.2;
}
body {
font-family: futura;
}
h2.title {
color: black;
text-align: center;
}
.axis {
font-family: arial;
font-size: 0.7em;
}
text {
fill: black;
}
.label {
font-size: 2em;
}
path {
fill: none;
stroke: black;
stroke-width: 1px;
}
.tick {
fill: none;
stroke: black;
}
.line {
fill: none;
stroke: #4eb0bb;
stroke-width: 1px;
}
</style>
<script>
function draw(data) {
"use strict";
​
/*
D3.js setup code
*/
​
// set margins according to Mike Bostock's margin conventions
// https://bl.ocks.org/mbostock/3019563
var margin = {top: 25, right: 40, bottom: 150, left: 75};
// set height and width of chart
var width = 1400 - margin.left - margin.right,
height = 800 - margin.top - margin.bottom;
// specify the radius of our circles and the
// column we want to plot
var field = 'San Francisco',
x_field = "number_of_reviews",
y_field = "availability_365";
radius_size = "reviews_per_month";
// Append the title for the graph
d3.select("body")
.append("h2")
.text(field + " Listings")
.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[y_field];
});
​
// bind our data to svg circles for the scatter plot
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
// maximum price
var max_y = d3.max(data, function(d) {
return +d[y_field];
});
// maximum radius
var max_radius = d3.max(data, function(d) {
return +d[radius_size];
});
// get min/max review count
var review_extent = d3.extent(data, function(d){
return +d[x_field];
});
​
// Create x-axis scale mapping dates -> pixels
var review_scale = d3.scale.linear()
.range([0, width])
.domain(review_extent);
​
// Create y-axis scale mapping price -> pixels
var measure_scale = d3.scale.linear()
.range([height, 0])
.domain([0, max_y]);
// Create radius scale mapping price -> pixels
var radius_scale = d3.scale.linear()
.range([0, 10])
.domain([0, max_radius]);
// Create D3 axis object from time_scale for the x-axis
var x_axis = d3.svg.axis()
.scale(review_scale);
​
// 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(x_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
d3.select(".y.axis")
.append("text")
.attr('class', 'label')
.text("Price (dollar/sq-ft)")
.attr("transform", "rotate(-90, -43, 0) translate(-400)");
​
// based on the data bound to each svg circle,
// change its center-x (cx) and center-y (cy)
// coordinates
d3.selectAll('circle')
.attr('cx', function(d) {
return review_scale(+d[x_field]);
})
.attr('cy', function(d) {
return measure_scale(+d[y_field]);
})
.attr('r', function(d) {
return radius_scale(+d[radius_size]);
})
.style('fill', function(d) {
switch (d['room_type']) {
case 'Entire home/apt':
return 'red';
case 'Private room':
return 'green'
case 'Shared room':
return 'blue';
default:
return 'gray';
}
});
}
</script>
</head>
<body>
<script>
/*
Use D3 to load the CSV file and pass
the contents of it to the draw function.
*/
d3.csv("https://jay-oh-en.github.io/interactive-data-viz/data/airbnb/listings.csv", draw);
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.8/d3.min.js