Public
Edited
Sep 25, 2024
Insert cell
Insert cell
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 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
latScale = d3.scaleLinear().domain([-90, 90]).range([300, 900]).clamp()
Insert cell
latScale(200)
Insert cell
Insert cell
exampleLogScale = d3
.scalePow()
.exponent(0.01)
.domain([1, 10000])
.range([200, 600])
Insert cell
{
//svg variables
const height = 100;

//create SVG artboard
const svg = d3.create("svg").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
d3.extent([20, 103, 13, 4, 40, 13, 12, 193])
Insert cell
Insert cell
Insert cell
MinAndMax = d3.extent(colors, (c) => c.waveLength)
Insert cell
Insert cell
{
const min = d3.min(colors, (c) => c.waveLength);
const max = d3.max(colors, (c) => c.waveLength);
const mean = d3.mean(colors, (c) => c.waveLength);
const median = d3.median(colors, (c) => c.waveLength);
const extent = d3.extent(colors, (c) => c.waveLength);

return {
minimum: min,
maximum: max,
average: mean,
median: median,
extent: extent,
data: colors
};
}
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
viewof moonPhase = Inputs.range([0.0, 1.0], {
label: "Moon Phase",
value: 0.5,
step: 0.01
})
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
alphabeticalStates = states.sort((a, b) => d3.ascending(a.name, b.name))
Insert cell
alphabeticalStates[0]
Insert cell
Insert cell
populationSortedStates = states.sort((a, b) =>
d3.ascending(a.population, b.population)
)
Insert cell
populationSortedStates[0]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
betterCirclePlot = {
//svg variables
const height = 200;
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, states.length])
.range([margin, width - margin]);

const populationToRadius = d3
.scaleLinear()
.domain(d3.extent(states, (d) => d.population))
.range([1, 15]);

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

//loop through all items in dataset
for (let i = 0; i < states.length; i++) {
//save current state in variable for reuse
const state = states[i];

//draw circle for each item, using scales!
svg
.append("circle")
.attr("cx", indexToX(i))
.attr("cy", height / 2)
.attr("r", populationToRadius(state.population))
.attr("fill", d3.interpolateCool(populationToParameter(state.population)))
.attr("opacity", 1);

//check if i is even or odd (i%2 == 0), and assign alternating y positions
//if i is even, set the labelY to height divided by two, minus 25
//otherwise, i is odd, and labelY should be set to height divided by two, plus 25
const labelY = i % 2 == 0 ? height / 2 - 25 : height / 2 + 25;

//draw labels
svg
.append("text")
.attr("x", indexToX(i))
.attr("y", labelY)
.attr("font-size", 10)
.attr("font-family", "Courier")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "middle")
//substring cuts certain characters from a string
.text(stateLUT[states[i].name]);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
sortedStates = states.sort((a, b) => d3.ascending(a[sortKey], b[sortKey]))
Insert cell
betterRectPlot = {
//svg variables
const height = 800;
const margin = 30;
const leftMargin = 150;

//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, sortedStates.length])
.range([margin, height - margin]);

const populationToWidth = d3
.scaleLinear()
.domain(d3.extent(sortedStates, (d) => d.population))
.range([50, width - (leftMargin + margin)]);

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

const barHeight = (height - margin * 2) / sortedStates.length;

//loop through all items in dataset
for (let i = 0; i < sortedStates.length; i++) {
//save current state for reuse
const state = sortedStates[i];

//draw rect for each item
svg
.append("rect")
.attr("x", leftMargin)
.attr("y", indexToY(i))
.attr("width", populationToWidth(state.population))
.attr("height", barHeight)
.attr(
"fill",
d3.interpolateCool(populationToParameter(state.population))
);

//draw labels for each item
svg
.append("text")
.attr("x", leftMargin - 10)
.attr("y", indexToY(i) + barHeight / 2)
.attr("font-size", 10)
.attr("font-family", "Courier")
.attr("text-anchor", "end")
.attr("dominant-baseline", "middle")
.text(state.name);
}

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

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