Published
Edited
Apr 17, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// importing json file
bosNeighborhoods = d3.json('https://gist.githubusercontent.com/cesandoval/09b2e39263c748fbcb84b927cecc7c46/raw/ab71d3638efd2545ec99c2651c6f2ddcea9d2a07/boston.json')
Insert cell
// importing csv
tweets = d3.csv('https://gist.githubusercontent.com/cesandoval/046a91586ae76889aeb5b3e9db53016e/raw/ffb0c410ce8503c8c839cde01235bafb39cb14ad/bostosn_311.csv')
Insert cell
// cleaning data to have only the number of tweets per neighborhood
tweetsclean = {
const req = {}
tweets.forEach(d => (req[d.id] = (+d.twitter))); // id (neighborhood) + twitter (total number of tweets)
return req;
}
Insert cell
width = 700
Insert cell
height = 580
Insert cell
color = d3.scaleQuantize()
.domain([0, 5])
.range(d3.schemePurples[9]); // defining the purple color scheme
Insert cell
// defining the projection
bosProjection = d3.geoAlbers()
.scale( 190000 )
.rotate( [71.057,0] )
.center( [0, 42.313] )
.translate( [width/2,height/2] );
Insert cell
// Create GeoPath function that uses built-in D3 functionality to turn lat/lon coordinates into screen coordinates
bos_geoPath = d3.geoPath()
.projection( bosProjection );
Insert cell
{
// Create SVG
let svg = d3.select(DOM.svg(width, height));

// Append empty placeholder g element to the SVG
// g will contain geometry elements
let g = svg.append("g");

// importing tooltip
tooltip
g.selectAll( "path" )
.data(topojson.feature(bosNeighborhoods, bosNeighborhoods.objects.boston_neigh).features) // defining data
.enter()
.append( "path" )
.attr( "fill", d => color(Math.log(tweetsclean[d.properties.OBJECTID]))) // adding a fill according to the total number of tweets per neighborhood
.attr( "stroke", "#333")
.attr( "d", bos_geoPath ); // adding coordinate system
return svg.node();
}
Insert cell
Insert cell
// creating tooltip
tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("font-family", "'Open Sans', sans-serif")
.style("font-size", "12px")
.style("background", "white") // adding a white background
.style("padding", "5px") // adding the padding
.style("opacity",0.6) // adding opacity
.style("z-index", "10")
.style("visibility", "hidden");
Insert cell
{
// Create SVG
let svg = d3.select(DOM.svg(width, height));

// Append empty placeholder g element to the SVG
// g will contain geometry elements
let g = svg.append("g");

tooltip

g.selectAll( "path" )
.data(topojson.feature(bosNeighborhoods, bosNeighborhoods.objects.boston_neigh).features)
.enter()
.append( "path" )
.attr( "fill", d => color(Math.log(tweetsclean[d.properties.OBJECTID])))
.attr( "stroke", "#333")
.attr( "d", bos_geoPath )
// adding the mouseover effect
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.properties.Name))
.on("mousemove", d => tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.properties.Name + ": " + (tweetsclean[d.properties.OBJECTID]/558)*100 + "%")) // adding the neighborhood name: percentage of tweets
.on("mouseout", d => tooltip.style("visibility", "hidden"));
return svg.node();
}
Insert cell
Insert cell
{
// Create SVG
let svg = d3.select(DOM.svg(width, height));

// Append empty placeholder g element to the SVG
// g will contain geometry elements
let g = svg.append("g")
.call(legend);
// Classic D3... Select non-existent elements, bind the data, append the elements, and apply attributes
g.selectAll( "path" )
.data(topojson.feature(bosNeighborhoods, bosNeighborhoods.objects.boston_neigh).features)
.enter()
.append( "path" )
.attr( "fill", d => color(Math.log(tweetsclean[d.properties.OBJECTID])))
.attr( "stroke", "#333")
.attr( "d", bos_geoPath )
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.properties.Name))
.on("mousemove", d => tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.properties.Name + ": " + (tweetsclean[d.properties.OBJECTID]/558)*100 + "%"))
.on("mouseout", d => tooltip.style("visibility", "hidden"));
return svg.node();
}
Insert cell
// creating the legend
legend = g => {
const x = d3.scaleLinear()
.domain(d3.extent(color.domain()))
.rangeRound([0, 250]);

g.selectAll("rect")
.data(color.range().map(d => color.invertExtent(d)))
.join("rect")
.attr("height", 10)
.attr("x", d => x(d[0]))
.attr("width", d => x(d[1]) - x(d[0]))
.attr("fill", d => color(d[0])); // color of the legend

g.append("text")
.attr("x", x.range()[0])
.attr("y", 50)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Total number of tweets per neighborhood"); // title

g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(d => d3.format(".2n")(d)) // defining decimal numbers for the legend
.tickValues(color.range().slice(1).map(d => color.invertExtent(d)[0])))
.select(".domain")
.remove();
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more