Public
Edited
Nov 17, 2023
2 forks
6 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
grouped_racial_data = {
let grouped_racial_data = d3.rollup(
raw_racial_data,
(a) => a[0],
(o) => o.fips
);

return grouped_racial_data;
}
Insert cell
raw_racial_data = {
let raw_racial_data = await (
await FileAttachment("racial_and_ethnic_data@1.csv")
).csv();
raw_racial_data.forEach(function (o) {
let fips = o.state + o.county + o.tract + o["block group"];
o.fips = fips;
let total_pop = o.B02001_001E;
o["Asian"] = o.B02001_005E / total_pop;
o["African American"] = o.B02001_003E / total_pop;
o.Hispanic = o.B03003_003E / total_pop;
o["Indigenous American"] = o.B02001_004E / total_pop;
o["White"] = d3.min([o.B02001_002E / total_pop, 0.999]);
o["Asian cnt"] = o.B02001_005E;
o["African American cnt"] = o.B02001_003E;
o["Hispanic cnt"] = o.B03003_003E;
o["Indigenous American cnt"] = o.B02001_004E;
o["White cnt"] = o.B02001_002E;
});

return raw_racial_data;
}
Insert cell
racial_descriptors = FileAttachment("racial_variable_descriptions.csv").csv()
Insert cell
Inputs.table(racial_descriptors, { columns: ["label", "attributes"] })
Insert cell
towns = [
{ name: "Avery Creek", lat: 35.460278, lon: -82.578889 },
{ name: "Barnardsville", lat: 35.7775, lon: -82.454722 },
{ name: "Black Mountain", lat: 35.619167, lon: -82.325556 },
{ name: "Montreat", lat: 35.645556, lon: -82.300556 },
{ name: "Sandy Mush", lat: 35.6591591, lon: -82.882654 },
{ name: "Weaverville", lat: 35.696944, lon: -82.560556 },
{ name: "Leicester", lat: 35.65447891099802, lon: -82.69602925026236 },
{ name: "Royal Pines", lat: 35.477883861797125, lon: -82.50429384436976 },
{ name: "Beaverdam", lat: 35.49851910659069, lon: -82.6894122638762 },
{ name: "Candler", lat: 35.535366413680244, lon: -82.69303350857533 },
{ name: "Fairview", lat: 35.51294756477446, lon: -82.39591841246357 }
]
Insert cell
geo_data = {
let buncombe_blockgroups2021 = await FileAttachment(
"BuncombeBlockgroupsRoads.json"
).json();
let blockgroups = topojson.feature(
buncombe_blockgroups2021,
buncombe_blockgroups2021.objects.blockgroups
);
let boundary = topojson.feature(
buncombe_blockgroups2021,
buncombe_blockgroups2021.objects.boundary
);
let roads = topojson.feature(
buncombe_blockgroups2021,
buncombe_blockgroups2021.objects.roads
);

return { blockgroups, boundary, roads };
}
Insert cell
import { Legend } from "@d3/color-legend"
Insert cell
group
Insert cell
{
let w = d3.min([1100, width]);
let h = 0.625 * w;
let projection = d3
.geoConicEqualArea()
.parallels([34.333, 36.1666])
.rotate([79, 0])
.fitSize([w - 10, h], geo_data.boundary);
let path = d3.geoPath().projection(projection);

let div = d3.create("div").style("width", `${w}px`).style("height", `${h}px`);
let svg = div.append("svg").attr("width", w).attr("height", h);

let map = svg.append("g").attr("id", "map");

let base_layer = map.append("g").attr("id", "base_layer");

let color_scale;
if (group == "African American" || group == "White" || group == "Hispanic") {
color_scale = d3
.scaleLinear()
.interpolate(() => d3.interpolateBlues)
.domain([0, 1]);
} else if (group == "Asian") {
color_scale = d3
.scaleThreshold()
.domain([0.0000001, 0.05, 0.1])
.range(d3.schemeBlues[6].slice(0, 4));
} else if (group == "Indigenous American") {
color_scale = d3
.scaleThreshold()
.domain([0.0000001, 0.02])
.range(d3.schemeBlues[6].slice(0, 3));
}

base_layer
.selectAll("path")
.data(geo_data.blockgroups.features)
.join("path")
.attr("d", path)
.attr("fill", (d) =>
color_scale(
grouped_racial_data.get(d.properties.GEOID)["B02001_001E"] / 6200
)
)
.attr("data-geoid", (d) => d.properties.GEOID)
.attr("stroke", "black")
.attr("stroke-width", 0.3)
.append("title")
.text((d) =>
d3.format("D")(grouped_racial_data.get(d.properties.GEOID)["B02001_001E"])
);

let road_group = map.append("g").attr("class", "roads").attr("opacity", 1);
road_group
.append("g")
.selectAll("path.road")
.data(geo_data.roads.features)
.join("path")
.attr("class", "road context")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-width", 2.5)
.attr("stroke-linejoin", "round")
.attr("d", path)
.style("pointer-events", "none");
road_group
.append("g")
.selectAll("path.road")
.data(geo_data.roads.features)
.join("path")
.attr("class", "road context")
.attr("fill", "none")
.attr("stroke", "#ddd")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("d", path)
.style("pointer-events", "none");
svg
.append("path")
.attr("d", path(geo_data.boundary.features[0]))
.attr("stroke", "black")
.attr("stroke-width", 3)
.attr("fill", "none");

let city_name_display = map
.append("g")
.attr("class", "towns")
.attr("opacity", 1);
city_name_display
.selectAll("text.city")
.data(towns)
.join("text")
.attr("class", "city context")
.attr("x", (d) => projection([d.lon, d.lat])[0])
.attr("y", (d) => projection([d.lon, d.lat])[1])
.attr("dx", (o) => (o.name == "Sandy Mush" ? 60 : 0))
.attr("opacity", 1)
.text((o) => o.name)
.style("font-family", "sans-serif")
.attr("font-size", 14)
.attr("pointer-events", "none")
.attr("text-anchor", "middle")
.attr("fill", group == "White" ? "white" : "black");

div.node().color_scale = color_scale;

return div.node();
}
Insert cell
d3.max(raw_racial_data.map((o) => parseInt(o.B02001_001E)))
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