Published
Edited
Oct 21, 2020
Insert cell
Insert cell
width = 1080
Insert cell
Insert cell
Insert cell
year = 2016
Insert cell
Insert cell
d3.sum(masterData, ({State_Abbr, C4a}) => !_.includes(['MN', 'NE'], State_Abbr) && C4a ? C4a[2018] || 0 : 0)
Insert cell
d3.sum(data, ({sum}) => sum)
Insert cell
colors = new Object({
bar: '#2D1832',
pattern: '#4E5255',
gray: '#AEA2B1',
})
Insert cell
{
const svg = d3.select(DOM.svg(width, height))
// scales
const margin = {left: 60, top: height * 0.25, right: 60, bottom: 60}
const xScale = d3.scaleLinear().domain([0, d3.max(data, d => d.sum)])
.range([margin.left, width - margin.right])
const yScale = d3.scaleBand().domain(_.map(data, 'label'))
.range([margin.top, height - margin.bottom])
.padding(0.2)
// add patterns
const patterns = _.reduce(_.keys(colors), (obj, color) => {
obj[color] = textures
.lines()
// .heavier()
// .thicker()
.size(4)
.strokeWidth(1)
.stroke(colors[color])
// .circles()
// .complement()
// .fill(colors[color])
svg.call(obj[color])
return obj
}, {})
// x-axis
const xAxis = d3.axisTop().scale(xScale)
.ticks(4).tickSize(-height + margin.top + margin.bottom).tickSizeOuter(0)
svg.append('g').attr('id', 'axis')
.attr('transform', `translate(0, ${margin.top})`).call(xAxis)
// draw bars
svg.append('g').attr('id', 'bars')
.selectAll('rect')
.data(data).join('rect')
.attr('transform', d => `translate(${margin.left}, ${yScale(d.label)})`)
.attr('width', d => xScale(d.sum) - margin.left)
.attr('height', yScale.bandwidth())
.attr('fill', colors.bar)
svg.append('g').attr('id', 'textures')
.selectAll('rect')
.data(data).join('rect')
.attr('transform', d => `translate(${margin.left}, ${yScale(d.label)})`)
.attr('width', d => xScale(d.sum) - margin.left)
.attr('height', yScale.bandwidth())
.attr('fill', patterns.pattern.url())
// texts
svg.append('g').attr('id', 'labels')
.selectAll('text')
.data(data).join('text')
.attr('transform', d =>
`translate(${xScale(d.sum) + 5}, ${yScale(d.label) + yScale.bandwidth() / 2})`)
.text(d => d.label)
svg.append('g').attr('id', 'sums')
.selectAll('text')
.data(data).join('text')
.attr('transform', d =>
`translate(${xScale(d.sum) + 5}, ${yScale(d.label) + yScale.bandwidth() / 2 + 16})`)
.text(d => d3.format(',')(d.sum))
return scrollSVG(svg.node())
}
Insert cell
missingStates = _.chain(masterData)
.groupBy('State_Full')
.map((counties, state) => {
const missing = _.filter(counties, d =>
_.some(['C4b', 'C4c', 'C4e'], key => !d[key] || !_.isNumber(d[key][year]) || _.isNaN(d[key][year])))
return {
state,
ratio: missing.length / counties.length,
}
}).filter(({ratio}) => ratio === 1)
.map('state').sortBy()
.value().join(', ')
Insert cell
Insert cell
d3 = require('d3')
Insert cell
_ = require('lodash')
Insert cell
textures = require('textures')
Insert cell
import {masterData, masterKeys} from '6cc733f467fac0dc'
Insert cell
import {scrollSVG} from '@sxywu/utility-functions'
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