Published
Edited
Mar 5, 2021
Importers
1 star
Insert cell
Insert cell
Insert cell
viewof apiKey = html`<input type=text>`
Insert cell
apiKey
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
stateCombined.clientWidth
Insert cell
width
Insert cell
Insert cell
countyCombined = html`
<div style="width: min-content; padding: 5px;">
<div style="border: 1px solid #333; border-radius: 8px; padding: 5px;"> <div style="text-align: center; width: 620px; font-weight: 700; font-size: 2rem;">${
stateCounties.find(d => d.county === county).NAME
} - ${d3.format('.3s')(
stateCounties.find(d => d.county === county).B01001_001E
)}</div>
<div style="display: grid; grid-template-columns: 300px 300px; grid-gap: 20px;">
<div>${countyMapX.cloneNode(true)}</div>
<div>${countyMapY.cloneNode(true)}</div>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
s = states.features.find(d => d.properties.STATEFP === state)
Insert cell
stateYMargin = ({
top: 10,
right: 70,
bottom: 10,
left: 10
})
Insert cell
projectionY = d3
.geoMercator()
.fitExtent(
[
[stateYMargin.left, stateYMargin.top],
[300 - stateYMargin.right, 300 - stateYMargin.bottom]
],
s
)
Insert cell
pathY = d3.geoPath(projectionY)
Insert cell
stateXMargin = ({
top: 35,
right: 10,
bottom: 10,
left: 10
})
Insert cell
Insert cell
Insert cell
countyYMargin = ({
top: 10,
right: 70,
bottom: 10,
left: 10
})
Insert cell
Insert cell
Insert cell
countyXMargin = ({
top: 35,
right: 10,
bottom: 10,
left: 10
})
Insert cell
countyProjectionX = d3
.geoMercator()
.fitExtent(
[
[countyXMargin.left, countyXMargin.top],
[300 - countyXMargin.right, 300 - countyXMargin.bottom]
],
c
)
Insert cell
countyPathX = d3.geoPath(countyProjectionX)
Insert cell
countyProjection = d3
.geoMercator()
.fitExtent([[10, 10], [300 - 10, 300 - 10]], c)
Insert cell
countyPath = d3.geoPath(countyProjection)
Insert cell
d3 = require('d3@6', "d3-geo-scale-bar@1.1.1")
Insert cell
census = {
const census = await require(await FileAttachment('citysdk-2.0.37.js').url());
return (...params) =>
new Promise((resolve, reject) => {
census(...params, (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
}
Insert cell
import { Select, Radio } from "@observablehq/inputs"
Insert cell
states = census({
vintage: "2017",
values: ["NAME", "B01001_001E"],
sourcePath: ["acs", "acs5"],
geoHierarchy: {
state: "*"
},
geoResolution: "20m",
statsKey: apiKey
})
Insert cell
stateCounties = census({
vintage: "2017",
values: ["NAME", "B01001_001E"],
sourcePath: ["acs", "acs5"],
geoHierarchy: {
state: state,
county: "*"
},
statsKey: apiKey,
})
Insert cell
stateTracts = census({
vintage: "2017",
values: ["B01001_001E"],
sourcePath: ["acs", "acs5"],
geoHierarchy: {
state: state,
tract: "*"
},
statsKey: apiKey,
geoResolution: "500k" // required
})
Insert cell
topojson = require('topojson-server', 'topojson-client')
Insert cell
c = topojson.merge(cbg, cbg.objects.blockgroups.geometries)
Insert cell
cbg = topojson.topology({ blockgroups: countyBlockGroups })
Insert cell
countyBlockGroups = census({
vintage: "2017",
values: ["B01001_001E"],
sourcePath: ["acs", "acs5"],
geoHierarchy: {
state: state,
county: county,
"block-group": "*"
},
statsKey: apiKey,
geoResolution: "500k" // required
})
Insert cell
sortedX = stateTracts.features
.slice()
.sort((a, b) => d3.descending(d3.geoCentroid(a)[0], d3.geoCentroid(b)[0]))
Insert cell
sortedY = stateTracts.features
.slice()
.sort((a, b) => d3.descending(d3.geoCentroid(a)[1], d3.geoCentroid(b)[1]))
Insert cell
stateTotal = d3.sum(stateTracts.features, d => d.properties.B01001_001E)
Insert cell
middleXi = {
let accum = 0;
for (const [i, tract] of sortedX.entries()) {
accum += tract.properties.B01001_001E;
if (accum >= stateTotal / 2) return i;
}
}
Insert cell
middleX = d3.geoCentroid(sortedX[middleXi])
Insert cell
middleYi = {
let accum = 0;
for (const [i, tract] of sortedY.entries()) {
accum += tract.properties.B01001_001E;
if (accum >= stateTotal / 2) return i;
}
}
Insert cell
middleY = d3.geoCentroid(sortedY[middleYi])
Insert cell
countySortedX = countyBlockGroups.features
.slice()
.sort((a, b) => d3.descending(d3.geoCentroid(a)[0], d3.geoCentroid(b)[0]))
Insert cell
countySortedY = countyBlockGroups.features
.slice()
.sort((a, b) => d3.descending(d3.geoCentroid(a)[1], d3.geoCentroid(b)[1]))
Insert cell
countyTotal = d3.sum(countyBlockGroups.features, d => d.properties.B01001_001E)
Insert cell
countyMiddleXi = {
let accum = 0;
for (const [i, tract] of countySortedX.entries()) {
accum += tract.properties.B01001_001E;
if (accum >= countyTotal / 2) return i;
}
}
Insert cell
countyMiddleX = d3.geoCentroid(countySortedX[countyMiddleXi])
Insert cell
countyMiddleYi = {
let accum = 0;
for (const [i, tract] of countySortedY.entries()) {
accum += tract.properties.B01001_001E;
if (accum >= countyTotal / 2) return i;
}
}
Insert cell
countyMiddleY = d3.geoCentroid(countySortedY[countyMiddleYi])
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