Published
Edited
Dec 16, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
redlining_airQuality = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => airQualityColor(airQualityByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `Air Quality Score: ${airQualityByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))}`);

// this part renders the census borders over top

svg.append("g")
.selectAll("path")
.data(redlinedNeighborhoods.features)
.join("path")
.attr("fill", "none")
.attr("stroke", d => d.properties.holc_grade == "D" ? "white" : "none")
.attr("stroke-width", "2px")
.attr("stroke-linejoin", "round")
.attr("d", path);

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html `<div>
<input type="checkbox" class="checkbox" value="A" onclick="redline_and_income()"><label>Income</label>
<input type="checkbox" class="checkbox" value="B" onclick="redlined_and_whitePop()"><label>White</label>
<input type="checkbox" class="checkbox" value="C" onclick="redlined_and_treeCover()"><label>Tree</label>
</div>`
Insert cell
redline_and_income = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => incomeColor(incomeByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `Median Household Income ($): ${incomeByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))}`);

// this part renders the redlining borders over top
svg.append("g")
.selectAll("path")
.data(redlinedNeighborhoods.features)
.join("path")
.attr("fill", "none")
.attr("stroke", d => d.properties.holc_grade == "D" ? "navy" : "none")
.attr("stroke-width", "4px")
.attr("stroke-linejoin", "arcs")
.attr("stroke-opacity", 0.8)
.attr("d", path);

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}
Insert cell
Insert cell
Insert cell
legend({
color: whitePopColors,
width: width - 20,
tickFormat: ",d",
ticks: 7,
title: "White Population (%)"})
Insert cell
whitePopColors = d3.scaleSequential(whitePopExtent, d3.interpolatePurples)
Insert cell
Insert cell
redlined_and_whitePop = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => whitePopColors(whitePopByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `White Population (%): ${d3.format(".1f")(whitePopByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, '')))}`);

// svg.append("path")
// .datum(neighborhoods)
// .attr("fill", "none")
// .attr("stroke", "white")
// .attr("stroke-linejoin", "arcs-clips")
// .attr("d", path);

// this part renders the redlining borders over top
svg.append("g")
.selectAll("path")
.data(redlinedNeighborhoods.features)
.join("path")
.attr("fill", "none")
.attr("stroke", d => d.properties.holc_grade == "D" ? "purple" : "none")
.attr("stroke-width", "4px")
.attr("stroke-linejoin", "arcs")
.attr("stroke-opacity", 0.8)
.attr("d", path);

var white_legend = legend({
color: whitePopColor,
width: width - 20,
tickFormat: ",d",
ticks: 7,
title: "White Population (%)"})

svg.append("white_legend")
.attr("transform", "translate(870,450)");

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
redlined_and_treeCover = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => treeCoverColor(treeCoverByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `Tree Cover (%): ${d3.format(".1f")(treeCoverByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, '')))}`);

// this part renders the redlining borders over top
svg.append("g")
.selectAll("path")
.data(redlinedNeighborhoods.features)
.join("path")
.attr("fill", "none")
.attr("stroke", d => d.properties.holc_grade == "D" ? "white" : "none")
.attr("stroke-width", "2px")
.attr("stroke-linejoin", "round")
.attr("d", path);

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, 975, 610]);

svg.append(legend)
.attr("transform", "translate(870,450)");

svg.append("g")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.join("path")
.attr("fill", d => color(data.get(d.id)))
.attr("d", path)
.append("title")
.text(d => `${d.properties.name}, ${states.get(d.id.slice(0, 2)).name}
// ${format(data.get(d.id))}`);

svg.append("path")
.datum(topojson.mesh(us, us.objects.states, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", path);

return svg.node();
}
Insert cell
Insert cell
imperviousSurfaceArea = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => imperviousAreaColor(imperviousAreaByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `Impervious Surface Area (%): ${d3.format(".1f")(imperviousAreaByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, '')))}`);

// this part renders the census borders over top
svg.append("path")
.datum(neighborhoods)
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", path);

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}
Insert cell
Insert cell
Insert cell
redlined_and_imperviousSurfaceArea = {
// we create an SVG with the width and height specified
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

svg.append("g")
.selectAll("path")
.data(neighborhoods.features)
.join("path")
// This line renders our population data
.attr("fill", d => imperviousAreaColor(imperviousAreaByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, ''))))
.attr("d", path)
.append("title")
.text(d => `Impervious Surface Area (%): ${d3.format(".1f")(imperviousAreaByNeighborhood.get(d.properties.TRACTCE.replace(/^0+/, '')))}`);

// this part renders the redlining borders over top
svg.append("g")
.selectAll("path")
.data(redlinedNeighborhoods.features)
.join("path")
.attr("fill", "none")
.attr("stroke", d => d.properties.holc_grade == "D" ? "white" : "none")
.attr("stroke-width", "2px")
.attr("stroke-linejoin", "round")
.attr("d", path);

// we need to return a DOM element.
// the .node() function returns the DOM element corresponding to the d3 selection.
return svg.node();
}
Insert cell
bi_variate = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, 975, 610]);

svg.append(legend)
.attr("transform", "translate(870,450)");

svg.append("g")
.selectAll("path")
.data(topojson.feature(neighborhoods.features)
.join("path")
.attr("fill", d => color(data.get(d.id)))
.attr("d", path)
// .append("title")
// .text(d => `${d.properties.name}, ${states.get(d.id.slice(0, 2)).name}
// ${format(data.get(d.id))}`);

svg.append("path")
.datum(topojson.mesh(us, us.objects.states, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", path);

return svg.node();
}
Insert cell
test = {
let rows = allVars.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number((row["_Median (A9 Final.Geojson1)"]-273.15)*(9/5)+32), Number(row["MCPA rating (Pollution Data - Sheet1.csv1)"])])
return new Map(rows)
}
Insert cell
surfaceTemp_AirQual = Object.assign(new Map(neighborhoods.features.properties), ({TRACTCE, _Median (A9 Final.Geojson1), ["MCPA rating (Pollution Data - Sheet1.csv1)"]}) => [["TRACTCE"], [+["_Median (A9 Final.Geojson1)"], +["MCPA rating (Pollution Data - Sheet1.csv1)"]]])), {title: ["Surface Temperature", "Air Quality"]})
Insert cell
Insert cell
neighborhoods.features[1].properties.TRACTCE.replace(/^0+/, '')
Insert cell
d3.format(".1f")(surfaceTempByNeighborhood.get("980000"))
Insert cell
surfaceTempByNeighborhood.get(neighborhoods.features[11].properties.TRACTCE.slice(1))
Insert cell
Insert cell
merged_data = FileAttachment("merged_and_cleaned.csv").csv()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
surfaceTempByNeighborhood = {
let rows = allVars5.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number((row["_Median (A9 Final.Geojson1)"]-273.15)*(9/5)+32)])
return new Map(rows)
}
Insert cell
incomeByNeighborhood = {
let rows = allVars6.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number(row["Median Hou (A9 Final.Geojson1)"])])
return new Map(rows)
}
Insert cell
whitePopByNeighborhood = {
let rows = allVars.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number((row["White Popu (A9 Final.Geojson1)"]/row["Total Popu (A9 Final.Geojson1)"])*100)])
return new Map(rows)
}
Insert cell
airQualityByNeighborhood = {
let rows = allVars2.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number(row["MCPA rating (Pollution Data - Sheet1.csv1)"])])
return new Map(rows)
}
Insert cell
treeCoverByNeighborhood = {
let rows = allVars3.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number(row["Percent tree cover"])])
return new Map(rows)
}
Insert cell
imperviousAreaByNeighborhood = {
let rows = allVars4.map(row => [String(d3.format("")(row["TRACTCE (a9 final.geojson1)"])), Number(row["Percent impervious area"])])
return new Map(rows)
}
Insert cell
Income_and_Temp_chart = Scatterplot(merged_data, {
x: d => d['Median Hou (A9 Final.Geojson1)'],
y: d => d['_Median (A9 Final.Geojson1)'],
// -273.15 *(9/5)+32 ,
xLabel: "Median Income ($) →",
yLabel: "↑ Surface Temperature (F)",
xDomain: [0,120000],
yDomain: [302.5, 308],
stroke: "steelblue",
width,
height: 600,
})
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/scatterplot
function Scatterplot(data, {
x = ([x]) => x, // given d in data, returns the (quantitative) x-value
y = ([, y]) => y, // given d in data, returns the (quantitative) y-value
r = 3, // (fixed) radius of dots, in pixels
title, // given d in data, returns the title
marginTop = 20, // top margin, in pixels
marginRight = 30, // right margin, in pixels
marginBottom = 30, // bottom margin, in pixels
marginLeft = 40, // left margin, in pixels
inset = r * 2, // inset the default range, in pixels
insetTop = inset, // inset the default y-range
insetRight = inset, // inset the default x-range
insetBottom = inset, // inset the default y-range
insetLeft = inset, // inset the default x-range
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
xType = d3.scaleLinear, // type of x-scale
xDomain, // [xmin, xmax]
xRange = [marginLeft + insetLeft, width - marginRight - insetRight], // [left, right]
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
yRange = [height - marginBottom - insetBottom, marginTop + insetTop], // [bottom, top]
xLabel, // a label for the x-axis
yLabel, // a label for the y-axis
xFormat, // a format specifier string for the x-axis
yFormat, // a format specifier string for the y-axis
fill = "none", // fill color for dots
stroke = "currentColor", // stroke color for the dots
strokeWidth = 1.5, // stroke width for dots
halo = "#000", // color of label halo
haloWidth = 6 // padding around the labels
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);
const T = title == null ? null : d3.map(data, title);
const I = d3.range(X.length).filter(i => !isNaN(X[i]) && !isNaN(Y[i]));

// Compute default domains.
if (xDomain === undefined) xDomain = d3.extent(X);
if (yDomain === undefined) yDomain = d3.extent(Y);

// Construct scales and axes.
const xScale = xType(xDomain, xRange);
const yScale = yType(yDomain, yRange);
const xAxis = d3.axisBottom(xScale).ticks(width / 80, xFormat);
const yAxis = d3.axisLeft(yScale).ticks(height / 50, yFormat);

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");

svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("y2", marginTop + marginBottom - height)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", width)
.attr("y", marginBottom - 4)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text(xLabel));

svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));

svg.append("g")
.attr("fill", fill)
.attr("stroke", stroke)
.attr("stroke-width", strokeWidth)
.selectAll("circle")
.data(I)
.join("circle")
.attr("cx", i => xScale(X[i]))
.attr("cy", i => yScale(Y[i]))
.attr("r", r);

if (T) svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.selectAll("text")
.data(I)
.join("text")
.attr("dx", 7)
.attr("dy", "0.35em")
.attr("x", i => xScale(X[i]))
.attr("y", i => yScale(Y[i]))
.text(i => T[i])
.call(text => text.clone(true))
.attr("fill", "none")
.attr("stroke", halo)
.attr("stroke-width", haloWidth);

return svg.node();
}
Insert cell
Plot.plot(merged_data{
y: {
label: "↑ Temperature (°F)",
transform: f => f -273.15 *(9/5)+32 // convert Celsius to Fahrenheit
},
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Red_Line_and_Demographic_chart = PieChart(merged_data, {
name: d => d['Holc Grade'] == "D" ,
value: d => d.whitePopByNeighborhood,
.append("title")
.text(d => `White Population (%): ${d3.format(".1f"));
width,
height: 500
})
Insert cell
import {PieChart} from "@d3/pie-chart"
Insert cell
// import {Scatterplot} from "@d3/scatterplot"
Insert cell
import {Choropleth} from "@d3/choropleth"
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