Public
Edited
Nov 17, 2022
Insert cell
Insert cell
Insert cell
Insert cell
censusData = await d3.json(
"https://api.census.gov/data/2021/acs/acs1?get=NAME,B01001_001E&for=state:*"
)
Insert cell
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: state[2]
});
}
return statesData;
}
Insert cell
Insert cell
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", states[i].population / 50000)
.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
alphabeticalStates = states.sort((a, b) => d3.ascending(a.name, b.name))
Insert cell
Insert cell
exampleScale = d3.scaleLinear().domain([0, 10]).range([200, 600])
Insert cell
Insert cell
exampleScale(5)
Insert cell
Insert cell
{
//svg variables
const width = 800;
const height = 100;

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

//simple data
const exampleData = [9, 2, 7.1, 5, 0, 1, 6, 3.15, -3, 13];

//draw horizontal line
svg
.append("line")
.attr("x1", 200)
.attr("y1", height / 2)
.attr("x2", 600)
.attr("y2", height / 2)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "2");

//loop through all items in dataset
for (let i = 0; i < exampleData.length; i = i + 1) {
//convert data to pixels
const xPosition = exampleScale(exampleData[i]);

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height / 2)
.attr("r", 5)
.attr("fill", "orange")
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw text for each item
svg
.append("text")
.attr("x", xPosition)
.attr("y", height / 2 - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.text(exampleData[i] + "→" + exampleScale(exampleData[i]));
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
exampleLogScale = d3
.scalePow()
.exponent(0.01)
.domain([1, 10000])
.range([200, 600])
Insert cell
{
//svg variables
const width = 800;
const height = 100;

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

//dataset
const exampleData = [1, 10, 100, 1000, 10000, 100000];

//draw horizontal line
svg
.append("line")
.attr("x1", 200)
.attr("y1", height / 2)
.attr("x2", 600)
.attr("y2", height / 2)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "2");

//loop through all items in dataset
for (let i = 0; i < exampleData.length; i = i + 1) {
//convert data to pixels
const xPosition = exampleLogScale(exampleData[i]);

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height / 2)
.attr("r", 5)
.attr("fill", "orange")
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw text for each item
svg
.append("text")
.attr("x", xPosition)
.attr("y", height / 2 - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.text(exampleData[i] + "→" + Math.round(exampleLogScale(exampleData[i])));
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
exampleFlipScale = d3.scaleLinear().domain([0, 10]).range([600, 200])
Insert cell
{
//svg variables
const width = 800;
const height = 100;

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

//dataset
const exampleData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

//draw horizontal line
svg
.append("line")
.attr("x1", 200)
.attr("y1", height / 2)
.attr("x2", 600)
.attr("y2", height / 2)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "2");

//loop through all items in dataset
for (let i = 0; i < exampleData.length; i = i + 1) {
//convert data to pixels
const xPosition = exampleFlipScale(exampleData[i]);

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height / 2)
.attr("r", 5)
.attr("fill", "orange")
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw text for each item
svg
.append("text")
.attr("x", xPosition)
.attr("y", height / 2 - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.text(
exampleData[i] + "→" + Math.round(exampleFlipScale(exampleData[i]))
);
}

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

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
{
//svg variables
const width = 800;
const height = 100;

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

//create empty dataset
const exampleData = [];

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

//extract the min and the max of the dataset
const exampleExtent = d3.extent(exampleData);

//create scale to convert data to pixels
const exampleScale = d3.scaleLinear().domain(exampleExtent).range([200, 600]);

//draw horizontal line
svg
.append("line")
.attr("x1", 200)
.attr("y1", height / 2)
.attr("x2", 600)
.attr("y2", height / 2)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "2");

//loop through all items in dataset
for (let i = 0; i < exampleData.length; i = i + 1) {
//convert data to pixels
const xPosition = exampleScale(exampleData[i]);

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height / 2)
.attr("r", 5)
.attr("fill", "orange")
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw text for each item
svg
.append("text")
.attr("x", xPosition)
.attr("y", height / 2 - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.text(
exampleData[i].toFixed(1) +
"→" +
exampleScale(exampleData[i]).toFixed(1)
);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
{
const parameterScale = d3.scaleLinear().domain([0, 10]).range([0, 1]);

return d3.interpolateViridis(parameterScale(5));
}
Insert cell
Insert cell
{
//svg variables
const width = 800;
const height = 100;

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

//simple data
const exampleData = [1, 2, 3, 4, 5, 6, 7, 8, 9];

//create scale to convert data to pixels
const pixelScale = d3.scaleLinear().domain([0, 10]).range([200, 600]);

//create scale to convert data to number between 0 and 1
const parameterScale = d3.scaleLinear().domain([0, 10]).range([0, 1]);

const scaleNames = ["viridis", "magma", "cividis"];

for (let i = 0.25; i <= 0.75; i = i + 0.25) {
//draw horizontal line
svg
.append("line")
.attr("x1", 200)
.attr("y1", height * i)
.attr("x2", 600)
.attr("y2", height * i)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "2");
//draw label
svg
.append("text")
.attr("x", 190)
.attr("y", height * i)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "end")
.style("alignment-baseline", "middle")
.text(scaleNames[i * 4 - 1]);
}
//loop through all items in dataset
for (let i = 0; i < exampleData.length; i = i + 1) {
//convert data to pixels
const xPosition = pixelScale(exampleData[i]);

//convert data to number between 0 and 1
const parameterData = parameterScale(exampleData[i]);

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height * 0.25)
.attr("r", 10)
.attr("fill", d3.interpolateViridis(parameterData))
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height * 0.5)
.attr("r", 10)
.attr("fill", d3.interpolateMagma(parameterData))
.attr("stroke", "black")
.attr("stroke-width", "2");

//draw circle for each item
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", height * 0.75)
.attr("r", 10)
.attr("fill", d3.interpolateCividis(parameterData))
.attr("stroke", "black")
.attr("stroke-width", "2");
}
//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
{
if (moonPhase >= 0.93) {
return "🌕";
} else if (moonPhase >= 0.79) {
return "🌖";
} else if (moonPhase >= 0.65) {
return "🌗";
} else if (moonPhase >= 0.51) {
return "🌘";
} else if (moonPhase >= 0.37) {
return "🌑";
} else if (moonPhase >= 0.23) {
return "🌒";
} else if (moonPhase >= 0.09) {
return "🌓";
} else {
return "🌕";
}
}
Insert cell
Insert cell
Insert cell
booleanSlider > 0.5
Insert cell
Insert cell
Insert cell
Insert cell
{
if (distance > 0.75 && time < 0.25) {
return "Recommended Transit Method: 🚀";
} else if (distance > 0.5 && time < 0.5) {
return "Recommended Transit Method: 🏎";
} else if (distance > 0.25 && time < 0.75) {
return "Recommended Transit Method: 🚲";
} else if (distance >= 0 && time <= 1) {
return "Recommended Transit Method: 🛼";
}
}
Insert cell
Insert cell
Insert cell
grapeAge < 21 ? "🍇->🧃" : "🍇->🍷"
Insert cell
Insert cell
Insert cell
9 % modulo
Insert cell
Insert cell
Insert cell
isItEvenOrOdd % 2 == 0 ? "Even" : "Odd"
Insert cell
Insert cell
betterCirclePlot = {
//svg variables
const height = 400;
const margin = 20;

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

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

//scales to transform data to relevant visualization values
const indexToX = d3
.scaleLinear()
.domain([0, alphabeticalStates.length])
.range([margin, width - margin]);

const populationToRadius = d3
.scaleLinear()
.domain(d3.extent(alphabeticalStates, (d) => d.population))
.range([2, (width - margin * 2) / alphabeticalStates.length]);

const populationToParameter = d3
.scaleLinear()
.domain(d3.extent(alphabeticalStates, (d) => d.population))
.range([0, 1]);

//loop through all items in dataset
for (let i = 0; i < alphabeticalStates.length; i++) {
//draw circle for each item
svg
.append("circle")
.attr("cx", indexToX(i))
.attr("cy", height / 2)
.attr("r", populationToRadius(alphabeticalStates[i].population))
.attr(
"fill",
d3.interpolateViridis(
populationToParameter(alphabeticalStates[i].population)
)
)
.attr("opacity", 1);

//check if i is even or odd (i%2 == 0), and assign alternating y positions
const labelY = i % 2 == 0 ? height / 2 - 30 : height / 2 + 30;

//draw labels
svg
.append("text")
.attr("x", indexToX(i))
.attr("y", labelY + 4)
.attr("font-size", 8)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "center")
//substring cuts certain characters from a string
.text(states[i].name.substring(0, 8));
}

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

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

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

//scales to transform data to relevant visualization values
const indexToY = d3
.scaleLinear()
.domain([0, alphabeticalStates.length])
.range([margin, height - margin]);

const populationToWidth = d3
.scaleLinear()
.domain(d3.extent(alphabeticalStates, (d) => d.population))
.range([50, 400]);

const populationToParameter = d3
.scaleLinear()
.domain(d3.extent(alphabeticalStates, (d) => d.population))
.range([0, 1]);

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

//draw rect for each item
svg
.append("rect")
.attr("x", 150)
.attr("y", indexToY(i))
.attr("width", populationToWidth(alphabeticalStates[i].population))
.attr("height", height / alphabeticalStates.length)
.attr(
"fill",
d3.interpolateMagma(
populationToParameter(alphabeticalStates[i].population)
)
);

//draw labels for each item
svg
.append("text")
.attr("x", margin)
.attr("y", indexToY(i) + height / alphabeticalStates.length)
//the extra addition is required since text is set with its bottom-left coordinate, but rectangles are set with their top left
.attr("font-size", 8)
.text(states[i].name);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//B01001_001E is Total Population
//B16001_105E is Arabic speaking population
//B16001_003E is Spanish speaking populations

languageData = await d3.json(
"https://api.census.gov/data/2021/acs/acs1?get=NAME,B01001_001E,B16001_105E,B16001_003E&for=state:*"
)
Insert cell
languageStates = {
const data = [];

for (let i = 1; i < languageData.length; i++) {
const state = languageData[i];
data.push({
name: state[0],
totalPopulation: parseInt(state[1]),
arabic: state[3] == null ? 0 : parseInt(state[2]),
arabicPercent: state[3] == null ? 0 : parseInt(state[2]) / state[1],
spanish: state[3] == null ? 0 : parseInt(state[3]),
spanishPercent: state[3] == null ? 0 : parseInt(state[3]) / state[1],
fipsCode: state[4]
});
}
return data;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more