Public
Edited
Sep 25, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
censusData = await d3.json(
"https://api.census.gov/data/2023/acs/acs1?get=NAME,B01001_001E&for=state:*"
)
Insert cell
Insert cell
Insert cell
censusData
Insert cell
Insert cell
Insert cell
Insert cell
censusData
Insert cell
Insert cell
states = {
const statesData = [];

//note we are starting at 1 to skip the first row!
for (let i = 1; i < censusData.length; i++) {
const state = censusData[i];
statesData.push({
name: state[0],
population: parseInt(state[1]),
fipsCode: parseInt(state[2])
});
}
return statesData;
}
Insert cell
Insert cell
circlePlot = {
//svg variables
const height = 200;
const margin = 20;

//create SVG artboard
const svg = d3.create("svg").attr("width", width).attr("height", height);

//loop through all items in dataset
for (let i = 0; i < states.length; i++) {
//draw circle for each item
svg
.append("circle")
.attr("cx", i * (width / states.length) + margin)
.attr("cy", height / 2)
.attr("r", states[i].population / 1000000)
.attr("fill", "blue")
.attr("opacity", 0.5);

//draw labels
svg
.append("text")
.attr("x", i * (width / states.length) + margin)
.attr("y", 50)
.attr("font-size", 8)
.attr("text-anchor", "middle")
.text(states[i].name);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
rectPlot = {
//svg variables
const height = 500;
const margin = 20;

//create SVG artboard
const svg = d3.create("svg").attr("width", width).attr("height", height);

//loop through all items in dataset
for (let i = 0; i < states.length; i++) {
const rowHeight = (height - margin * 2) / states.length;

//draw rect for each item
svg
.append("rect")
.attr("x", 150)
.attr("y", i * rowHeight + margin)
.attr("width", (width * states[i].population) / 100000000) //The big number here was determined just by adding zeroes!
.attr("height", height / states.length)
.attr("fill", "blue");

//draw labels
svg
.append("text")
.attr("x", 0)
//the extra rowHeight is required since text is set with its bottom-left coordinate, but rectangles are set with their top left
.attr("y", i * rowHeight + margin + rowHeight)
.attr("font-size", 8)
.text(states[i].name);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
geographies = ["county", "congressional%20district", "place"]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dataCodes.Walked
Insert cell
Insert cell
dataCodes.Drove alone
Insert cell
Insert cell
dataCodes["Drove alone"]
Insert cell
Insert cell
{
const transitOption = "Public Transit";
return dataCodes[transitOption];
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
acsUrl = "https://api.census.gov/data/" +
year +
"/acs/acs1?get=NAME," +
dataCodes[dataChoice] +
"&for=" +
geography +
"&in=state:17"
Insert cell
Insert cell
rawTransitPopData = await d3.json(acsUrl)
Insert cell
Insert cell
cleanTransitPopData = {
const geoData = [];

//note we are starting at 1 to skip the first row!
for (let i = 1; i < rawTransitPopData.length; i++) {
const geo = rawTransitPopData[i];
geoData.push({
name: geo[0],
count: parseInt(geo[1]) ? parseInt(geo[1]) : null, //this ternary checks for "null", which ACS uses
geoLimit: parseInt(geo[2]),
geoCode: parseInt(geo[3])
});
}
return geoData;
}
Insert cell
Insert cell
d3.min([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
d3.median([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
d3.mode([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
d3.mean([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
d3.max([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
d3.extent([0, 1, 2, 3, 4, 5, 5, 5, 6, 7])
Insert cell
Insert cell
{
//create empty dataset
const exampleData = [];

//fill up random dataset
for (let i = 0; i < 10; i = i + 1) {
exampleData.push(Math.random() * 100);
}

const min = d3.min(exampleData);
const max = d3.max(exampleData);
const mean = d3.mean(exampleData);
const extent = d3.extent(exampleData);

return {
minimum: min,
maximum: max,
average: mean,
extent: extent,
data: exampleData
};
}
Insert cell
Insert cell
d3.mean(states, (s) => s.population)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
transitPopUrl = "https://api.census.gov/data/" +
transitYear +
"/acs/acs1?get=NAME," +
drivingCodes +
"," +
otherTransitCodes +
"&for=state:*"
Insert cell
rawTransitData = await d3.json(transitPopUrl)
Insert cell
Insert cell
transitComparisonData = {
const transitData = [];

//note we are starting at 1 to skip the first row!
for (let i = 1; i < rawTransitData.length; i++) {
const state = rawTransitData[i];
transitData.push({
name: state[0],
driving: parseInt(state[1]) + parseInt(state[2]),
otherTransit:
parseInt(state[3]) +
parseInt(state[4]) +
parseInt(state[5]) +
parseInt(state[6]),
fipsCode: parseInt(state[7])
});
}
return transitData;
}
Insert cell
Insert cell
halfCircles = {
//set up for our grid of half-circles
let rows = 8;
let columns = 7;

//this keeps the SVG artboard consistent with our row:col ratio
const height = width * (rows / columns);

//size of circle for each state
const scale = 30;

//create SVG artboard
const svg = d3.create("svg").attr("width", width).attr("height", height);

//background color
svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "#f0f5f9");

//This is a nested for loop
//For every loop of y, we loop through all the columns of x
for (let y = 0; y < rows; y++) {
for (let x = 0; x < columns; x++) {
//determine which item we are currently operating on in the grid
//which row we're on (y) multiplied by number of columns, plus the current column count (x)
let i = y * columns + x;

//for convenience
let state = transitComparisonData[i];

//check if we are out of states to draw
if (i > transitComparisonData.length - 1) {
//kill the loop
break;
}
//calculate the percentage difference between car-based on non-car-based transit
let ratio = state.otherTransit / state.driving;

//find center point and add margin
let xCenter = (width / columns) * x + width / (columns * 2);
let yCenter = (height / rows) * y + height / (rows * 2);

//add half circle for drivers with SVG arc
svg
.append("path")
.attr(
"d",
"M " +
xCenter +
" " +
yCenter +
" a " +
scale +
" " +
scale +
" 0 0 0 " +
scale * 2 +
" 0"
)
//arcs are drawn from their sides, not centers, so we shift them back by their radius
.attr("transform", "translate(" + -scale + ",0)")
.attr("fill", "#6d819c");

//add half circle for non-drivers with SVG arc
svg
.append("path")
.attr(
"d",
"M " +
xCenter +
" " +
yCenter +
" a " +
scale * ratio +
" " +
scale * ratio +
" 0 0 1 " +
scale * ratio * 2 +
" 0"
)
//arcs are drawn from their sides, not centers, so we shift them back by their radius
.attr("transform", "translate(" + -scale * ratio + ",0)")
.attr("fill", "#75D701");

//state labels
svg
.append("text")
.attr("x", xCenter)
.attr("y", yCenter + scale + 20)
.attr("font-size", 12)
.attr("text-anchor", "middle")
.attr("font-family", "Monaco")
.attr("fill", "#274c5e")
.text(stateLUT[state.name]);
}
}

//show visualization in Observable
return svg.node();
}
Insert cell
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