Published
Edited
Sep 29, 2022
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
//svg variables
const width = 1000;
const height = 1000;

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

//dark background
const bg = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.attr("fill", "#121212");

//plot lines
const plot = svg
.append("rect")
.attr("x", 150)
.attr("y", 150)
.attr("width", 700)
.attr("height", 700)
.attr("fill", "none")
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.5");

//plotting vertical lines
for (let i = 250; i < 850; i = i + 100) {
const verticalPlotLines = svg
.append("line")
.attr("x1", i)
.attr("y1", 150)
.attr("x2", i)
.attr("y2", 850)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}

//plotting horizontal lines
for (let i = 250; i < 850; i = i + 100) {
const horizontalPlotLines = svg
.append("line")
.attr("x1", 150)
.attr("y1", i)
.attr("x2", 850)
.attr("y2", i)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}

//text
svg
.append("text")
.attr("x", width - 200)
.attr("y", height - 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("Spanish-speaking population");

svg
.append("text")
.attr("x", 200)
.attr("y", 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("Gujarati-speaking population");

//creating a data source to use
const censusData = [];

//cleaning data from the source and populating censusData
for (let i = 1; i < languageData.length; i++) {
const state = languageData[i];
censusData.push({
name: state[0],
totalPopulation: parseInt(state[1]),
gujarati: state[3] == null ? 0 : parseInt(state[2]),
gujaratiPercent: 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]
});
}

//extracting minimum and maximum numbers of gujarati and spanish speaking populations
const gujMin = d3.min(censusData, (d) => d.gujarati);
const gujMax = d3.max(censusData, (d) => d.gujarati);
const spanishMin = d3.min(censusData, (d) => d.spanish);
const spanishMax = d3.max(censusData, (d) => d.spanish);

//scaling values for gujarati and spanish
const gujScale = d3.scaleLinear().domain([gujMin, gujMax]).range([150, 850]);
const spanishScale = d3
.scaleLinear()
.domain([spanishMin, spanishMax])
.range([150, 850]);

//
const populationToParameter = d3
.scaleLinear()
.domain(d3.extent(censusData, (d) => d.spanish))
.range([0, 1]);

//loop through data to populate scatter plot
for (let i = 0; i < censusData.length; i++) {
//spanish on x-axis position
const xPosition = spanishScale(censusData[i].spanish);
//gujarati on y-axis position and inverting the plot
const yPosition = height - gujScale(censusData[i].gujarati);

//circles for each data point
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", yPosition)
.attr("r", 8)
.attr(
"fill",
d3.interpolateViridis(populationToParameter(censusData[i].spanish))
);

//text for each data point
svg
.append("text")
.attr("x", xPosition)
.attr("y", yPosition - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.style("fill", "white")
.text(censusData[i].name);
}

//show visualization in Observable
return svg.node();
}
Insert cell
Insert cell
{
//svg variables
const width = 1000;
const height = 1000;

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

//dark background
const bg = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.attr("fill", "#121212");

//plot lines
const plot = svg
.append("rect")
.attr("x", 150)
.attr("y", 150)
.attr("width", 700)
.attr("height", 700)
.attr("fill", "none")
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.5");

//plotting vertical lines
for (let i = 250; i < 850; i = i + 100) {
const verticalPlotLines = svg
.append("line")
.attr("x1", i)
.attr("y1", 150)
.attr("x2", i)
.attr("y2", 850)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}

//plotting horizontal lines
for (let i = 250; i < 850; i = i + 100) {
const horizontalPlotLines = svg
.append("line")
.attr("x1", 150)
.attr("y1", i)
.attr("x2", 850)
.attr("y2", i)
.attr("stroke", "#dedede")
.attr("stroke-width", "1px")
.attr("stroke-opacity", "0.2");
}

//text
svg
.append("text")
.attr("x", width - 200)
.attr("y", height - 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("Spanish-speaking population");

svg
.append("text")
.attr("x", 200)
.attr("y", 100)
.style("font-family", "Helvetica")
.style("font-size", 16)
.style("text-anchor", "middle")
.style("fill", "white")
.text("Gujarati-speaking population");

//creating a data source to use
const censusData = [];

//cleaning data from the source and populating censusData
for (let i = 1; i < languageData.length; i++) {
const state = languageData[i];
censusData.push({
name: state[0],
totalPopulation: parseInt(state[1]),
gujarati: state[3] == null ? 0 : parseInt(state[2]),
gujaratiPercent: 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]
});
}

//extracting minimum and maximum numbers of gujarati and spanish speaking populations
const gujMin = d3.min(censusData, (d) => d.gujaratiPercent);
const gujMax = d3.max(censusData, (d) => d.gujaratiPercent);
const spanishMin = d3.min(censusData, (d) => d.spanishPercent);
const spanishMax = d3.max(censusData, (d) => d.spanishPercent);

//scaling values for gujarati and spanish
const gujScale = d3.scaleLinear().domain([gujMin, gujMax]).range([150, 850]);
const spanishScale = d3
.scaleLinear()
.domain([spanishMin, spanishMax])
.range([150, 850]);

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

//loop through data to populate scatter plot
for (let i = 0; i < censusData.length; i++) {
//spanish on x-axis position
const xPosition = spanishScale(censusData[i].spanishPercent);
//gujarati on y-axis position and inverting the plot
const yPosition = height - gujScale(censusData[i].gujaratiPercent);

//circles for each data point
svg
.append("circle")
.attr("cx", xPosition)
.attr("cy", yPosition)
.attr("r", 8)
.attr(
"fill",
d3.interpolateViridis(
populationToParameter(censusData[i].spanishPercent)
)
);

//text for each data point
svg
.append("text")
.attr("x", xPosition)
.attr("y", yPosition - 20)
.style("font-family", "courier")
.style("font-size", 10)
.style("text-anchor", "middle")
.style("fill", "white")
.text(censusData[i].name);
}

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