Public
Edited
Mar 5, 2024
Insert cell
Insert cell
Insert cell
Insert cell
bosNeighborhoods = d3.json('https://gist.githubusercontent.com/cesandoval/09b2e39263c748fbcb84b927cecc7c46/raw/ab71d3638efd2545ec99c2651c6f2ddcea9d2a07/boston.json')
Insert cell
bos311 = (await d3.csv('https://gist.githubusercontent.com/cesandoval/046a91586ae76889aeb5b3e9db53016e/raw/ffb0c410ce8503c8c839cde01235bafb39cb14ad/bostosn_311.csv', d => (d3.autoType(d))))
Insert cell
color = d3.scaleQuantize()
.domain([0, d3.max(bos311, d => +Math.log(d.twitter))])
.range(d3.schemePurples[9]);
Insert cell
// your code here
{
let width = 750
let height = 600
let top_buffer = 50

// Create Projection and geoPath
const bosProjection = d3.geoAlbers()
.scale( 190000 )
.rotate( [71.057,0] )
.center( [0, 42.313] )
.translate( [width/2,(height/2 + top_buffer)] )
const bos_geoPath = d3.geoPath()
.projection( bosProjection )
// Create empty object for holding 311 dataset
const tweetsbyneigh = {};
// Create object referenceable by neighborhood, give it value from tweets
bos311.forEach(d => (tweetsbyneigh[d.Name] = +d.twitter));
// Create SVG canvas
let svg = d3.select(DOM.svg(width, height))

// append new group for legend
svg.append("g")
.attr("transform", "translate(400,30)")
.call(legend);

// Call tooltip
tooltip

// Classic D3... Select non-existent elements, bind the data, append the elements, and apply attributes
svg.selectAll( "path" )
.data( topojson.feature(bosNeighborhoods, bosNeighborhoods.objects.boston_neigh).features )
.enter()
.append( "path" )
.attr( "fill", d => color(Math.log(tweetsbyneigh[d.properties.Name])) )
.attr( "stroke", "#333")
.attr( "d", bos_geoPath )
// Code added after tooltip is called
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.properties.Name + ": " + tweetsbyneigh[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 + ": " + tweetsbyneigh[d.properties.Name]))
.on("mouseout", d => tooltip.style("visibility", "hidden"))
return svg.node()
}
Insert cell
{
// Create empty object for holding 311 dataset
const tweetsbyneigh = {};
// Create object referenceable by neighborhood, give it value from tweets
bos311.forEach(d => (tweetsbyneigh[d.Name] = +d.twitter+1));
return tweetsbyneigh
}
Insert cell
Insert cell
Insert cell
Insert cell
// your code here;
tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "1")
.style("visibility", "hidden")
.style("background","white")
.style("opacity","0.6")
.style("padding","5px")
.style("font-family", "'Open Sans', sans-serif")
.style("font-size", "12px");
Insert cell
Insert cell
// your code here
legend = g => {
const x = d3.scaleLinear()
.domain(d3.extent(color.domain()))
.rangeRound([0, 260]);

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

g.append("text")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text("Tweets per neighborhood (Log Scale)");

g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(d => Math.exp
(d).toFixed(1))
.tickValues(color.range().slice(1).map(d => color.invertExtent(d)[0])))
.select(".domain")
.remove();
}
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