Published
Edited
Apr 28, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3@5")
Insert cell
topojson = require("topojson-client@3")
Insert cell
z = require("zebras")
Insert cell
bos311 = d3.csv('https://gist.githubusercontent.com/cesandoval/046a91586ae76889aeb5b3e9db53016e/raw/ffb0c410ce8503c8c839cde01235bafb39cb14ad/bostosn_311.csv',({id, Name, Citizens_Connect_App, City_Worker_App, Constituent_Call, Employee_Generated, twitter, Self_Service }) => ({id:+id, Name: Name, Citizens_Connect_App : +Citizens_Connect_App, City_Worker_App : +City_Worker_App, Constituent_Call : +Constituent_Call, Employee_Generated : +Employee_Generated, twitter: +twitter, Self_Service : +Self_Service, total : +Citizens_Connect_App + +City_Worker_App + +Constituent_Call + +Employee_Generated + +twitter + +Self_Service}))
Insert cell
cols = bos311.columns.slice(2,8)
Insert cell
bos311.push({id:0,Name:"All Neighborhoods",Citizens_Connect_App:z.sum(z.getCol(cols[0],bos311)),
City_Worker_App:z.sum(z.getCol(cols[1],bos311)),
Constituent_Call:z.sum(z.getCol(cols[2],bos311)),
Employee_Generated:z.sum(z.getCol(cols[3],bos311)),
twitter:z.sum(z.getCol(cols[4],bos311)),
Self_Service:z.sum(z.getCol(cols[5],bos311))})
Insert cell
bos311
Insert cell
neighborhoods = {
let neigh_list = []
for (var i = 0;i<=24;i++){
neigh_list.push(bos311[i].Name)}
return neigh_list
}
Insert cell
// your code here
viewof selectedNeighborhood = DOM.select(neighborhoods)
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));

svg.append("g")

.selectAll("rect")
.data(currNeighborhood)
.join("rect")
.attr("x", x(0) + margin.left+50)
.attr("y", d => y(d.subMethod)-20)
.attr("width", d => x(d.amount)-x(0))
.attr("fill", "steelblue")
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", "white")
.attr("text-anchor", "end")
.style("font", "12px sans-serif")
.selectAll("text")
.data(currNeighborhood)
.join("text")
.attr("x", d => x(d.subMethod) - 4)
.attr("y", d => y(d.amount) + y.bandwidth() / 2)
//.attr("dy", "0.35em")

svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);

svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.text("Submission Method")
.attr("transform", "translate(20, 200) rotate(-90)");
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.text("Number of Calls Via Method")
.attr("transform", "translate(650, 600)");
//svg.append("g")
// .call(legend);

return svg.node();
}
Insert cell
margin = ({top: 10, right: 25, bottom: 20, left: 40})
Insert cell
height = 600
Insert cell
z.filter(r => r.Name == "Allston",bos311)[0]["twitter"]
Insert cell
currNeighborhood = {
let currdata = []
let currNeigh = z.filter(r=>r.Name==selectedNeighborhood,bos311)[0]
for (const i in cols){
currdata.push({subMethod:cols[i],amount:currNeigh[cols[i]]})}
return currdata
}
Insert cell
x = d3.scaleLinear()
.domain([0, d3.max(currNeighborhood, d => d.amount)])
.rangeRound([margin.left, width - margin.right - 16])
Insert cell
y = d3.scaleBand()
.domain(z.getCol("subMethod",currNeighborhood))
.range([height - margin.bottom,margin.top ])
.padding(0.1)
Insert cell
xAxis = g => g
.attr("transform", `translate(${margin.left+50},${height - margin.bottom - 20})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
//.call(g => g.selectAll(".domain").remove())
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left + 90},-20)`)
.call(d3.axisLeft(y).ticks(null, "s"))
//.call(g => g.selectAll(".domain").remove())
Insert cell
Insert cell
Insert cell
// your code here
bostontopo = d3.json('https://gist.githubusercontent.com/cesandoval/09b2e39263c748fbcb84b927cecc7c46/raw/ab71d3638efd2545ec99c2651c6f2ddcea9d2a07/boston.json')
Insert cell
color = d3.scaleQuantize()
.domain([0,d3.max(bos311, d=>Math.log(d.total))])
.range(d3.schemePurples[9]);
Insert cell
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("Log of Number of 311 Calls by Neighborhood");

g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(d => d3.format(",.2f")(d))
.tickValues(color.range().slice(1).map(d => color.invertExtent(d)[0])))
.select(".domain")
.remove();
}
Insert cell
{
let width = 700;
let height = 600;
let value = null;

let bosProjection = d3.geoAlbers()
.scale( 190000 )
.rotate( [71.057,0] )
.center( [0, 42.313] )
.translate( [width/2,height/2] );
let bos_geoPath = d3.geoPath()
.projection( bosProjection );

// Create SVG
let svg = d3.select(DOM.svg(width, height));

let g = svg.append("g");

// Create empty object for holding dataset
const callsbyNeigh = {};
// Create property for each ID, give it value from number of twitter calls and perc calls by twitter
bos311.forEach(d => (callsbyNeigh[d.id] = Math.log(d.total)));
//const tweetpercbyNeigh = {};
//bos311.forEach(d => (tweetpercbyNeigh[d.id] = d3.format(",.2f")(d.twitter/d.total*100)));

const outline = svg.append("path")
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-linejoin", "round")
.attr("pointer-events", "none");
// Bind TopoJSON data
g.selectAll("path")
.data(topojson.feature(bostontopo, bostontopo.objects.boston_neigh).features) // Bind TopoJSON data elements
.enter().append("path")
.attr("d", bos_geoPath)
.style("fill", d => color(callsbyNeigh[d.properties.OBJECTID])) //have to find the item in topojson that matches data id
.style("stroke", "white")
.on("click", d => {
const node = svg.node();
node.value = value = value === d.properties.OBJECTID ? null : d.properties.OBJECTID;
node.dispatchEvent(new CustomEvent("input"));
outline.attr("d", value ? bos_geoPath(d) : null);
});
svg.append("g")
.attr("transform", "translate(250,500)")
.call(legend);
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
clickedNeighborhood = {
let currdata = []
if (clicked==undefined){
let clickedNeigh = z.filter(r=>r.Name=="All Neighborhoods",bos311)[0]
for (const i in cols){
currdata.push({subMethod:cols[i],amount:clickedNeigh[cols[i]]})}
} else {
let clickedNeigh = z.filter(r=>r.id==clicked,bos311)[0]
for (const i in cols){
currdata.push({subMethod:cols[i],amount:clickedNeigh[cols[i]]})}
}
return currdata
}
Insert cell
neighborhoodName = {
let name = []
if (clicked==undefined) {
name = "All Neighborhoods";
} else {
let clickedNeigh = z.filter(r=>r.id==clicked,bos311)[0];
name = clickedNeigh.Name;
}
return name
}
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