Skip to content

Instantly share code, notes, and snippets.

@patricknelli
Last active November 15, 2015 23:09
Show Gist options
  • Save patricknelli/a61e208c37ea177cf83a to your computer and use it in GitHub Desktop.
Save patricknelli/a61e208c37ea177cf83a to your computer and use it in GitHub Desktop.
Civic Impact through Data Visualization: Exercise 1

Join the chat at https://gitter.im/Jay-Oh-eN/data-scientists-guide-apache-spark

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.

Exercises

  • Part 1 (you are here 👇): simple bubble chart visualizing 3 dimensions of the data.
  • Part 2: thematic map of AirBnB listings distribution across SF neighborhoods.
  • Final: interactive linked map and line plot of AirBnB activity per each neighborhood in SF.

The Data

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

<!DOCTYPE html>
<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
// http://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("http://jay-oh-en.github.io/interactive-data-viz/data/airbnb/listings.csv", draw);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment