Public
Edited
Feb 10, 2023
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof aq_data = aq.from(raw_data).view({height:150})
Insert cell
Insert cell
viewof filtered = aq_data.derive({
date: d => op.parse_date(d.year),
year: d => op.year(op.parse_date(d.year))+1, // make sure year parses correctly
pop: d => op.parse_int(d.civiliannoninstitutional)*1000,
percent_in_laborforce: d => op.parse_float(d.civilianlaborforcepercen),
unemp: d => op.parse_float(d.civilianlaborforceunempl)
})
.select('date', 'year', 'groupcode', 'populationgroup', 'pop', 'percent_in_laborforce', 'unemp')
.orderby('year', 'groupcode').view({height: 150})
Insert cell
Insert cell
Insert cell
Insert cell
groups = filtered.dedupe('populationgroup').array('populationgroup')
Insert cell
{
const selection = vl.selectPoint('Select')
.fields('populationgroup')
.init(groups[0])
.bind(vl.menu(groups));

return vl.markCircle()
.title({text: "Each point represents a population group in a certain year (2004-2020)",
subtitle: "Virginia, source: US Bureau of Labor Statistics"})
.data(filtered)
.params(selection)
.encode(
vl.x().fieldQ('percent_in_laborforce').title("Percent in Labor Force"),
vl.y().fieldQ('unemp').title("Unemployment Rate"),
vl.tooltip(['year', {'field': 'populationgroup', 'title': 'group'}]),
vl.color().if(selection, vl.value("gold")),
vl.stroke().if(selection, vl.value("black")),
vl.opacity().if(selection, vl.value("0.9")).value("0.4")
)
.render();
}
Insert cell
Insert cell
{
const brush = vl.selectInterval().encodings('x');

// dynamic query histogram - set brush to use this chart
const years = vl.markBar({width: 10})
.data(filtered)
.params(brush)
.encode(
vl.x().fieldT('date').title(null),
vl.y().mean('unemp').title('avg unemp')
)
.width(600).height(50);

// scatterplot - can use brush as variable of selected items in years chart
const unemp = vl.markCircle()
.title({text: "Each point represents a population group in a certain year (2004-2020)",
subtitle: "Virginia, source: US Bureau of Labor Statistics"})
.data(filtered)
.encode(
vl.x().fieldQ('percent_in_laborforce').title("Percent in Labor Force"),
vl.y().fieldQ('unemp').title("Unemployment Rate"),
vl.tooltip(['year', {'field': 'populationgroup', 'title': 'group'}]),
vl.color().if(brush, vl.value("gold")),
vl.stroke().if(brush, vl.value("black")),
vl.opacity().if(brush, vl.value("0.9")).value("0.4")
)
.width(600).height(400);

return vl.vconcat(years, unemp).spacing(5).render();
}
Insert cell
Insert cell
{
const brush = vl.selectInterval().encodings('x');
const x = vl.x().fieldQ('percent_in_laborforce').title('labor %');
const y = vl.y().fieldQ('unemp').title('unemp');
const base = vl.markCircle().encode(x, y)

const mini = base.params(brush).height(100).width(100); // set brush to operate on mini

const large = base.encode( // use brush as variable of selected items
x.scale({domain: brush}).title("Percent in Labor Force"),y.title("Unemployment Rate"),
vl.tooltip(['year', {'field': 'populationgroup', 'title': 'group'}])
)
.title({text: "Each point represents a population group in a certain year (2004-2020)",
subtitle: "Virginia, source: US Bureau of Labor Statistics"})
.width(600).height(400);

return vl.data(filtered).hconcat(large, mini).render();
}
Insert cell
Insert cell
viewof linedata = filtered.filter(d => op.startswith(d.populationgroup, "Total,")).view({height:150})
Insert cell
{
// select a point for which to provide details-on-demand
const hover = vl.selectPoint('hover')
.encodings('x') // limit selection to x-axis value
.on('mouseover') // select on mouseover events
.toggle(false) // disable toggle on shift-hover
.nearest(true); // select data point nearest the cursor

// predicate to test if a point is hover-selected
// return false if the selection is empty
const isHovered = hover.empty(false);
// define our base line chart of stock prices
const line = vl.markLine().encode(
vl.x().fieldT('date').title(null),
vl.y().fieldQ('unemp').title("Unemployment Rate"),
vl.color().fieldN('populationgroup').title("Population Group")
);
// shared base for new layers, filtered to hover selection
const base = line.transform(vl.filter(isHovered));

// mark properties for text label layers
const label = {align: 'left', dx: 5, dy: -5};
const white = {stroke: 'white', strokeWidth: 2};

return vl.data(linedata)
.layer(
line,
// add a rule mark to serve as a guide line
vl.markRule({color: '#aaa'}).transform(vl.filter(isHovered)).encode(vl.x().fieldT('date')),
// add circle marks for selected time points, hide unselected points
line.markCircle().params(hover) // use as anchor points for selection
.encode(vl.opacity().if(isHovered, vl.value(1)).value(0)),
// add white stroked text to provide a legible background for labels
base.markText(label, white).encode(vl.text().fieldQ('unemp')),
// add text labels
base.markText(label).encode(vl.text().fieldQ('unemp'))
)
.title({text: "Younger populations suffer higher unemployment",
subtitle: "Virginia, source: US Bureau of Labor Statistics"})
.width(700).height(400)
.render();
}
Insert cell
Insert cell
import {aq, op} from "@uwdata/arquero"
Insert cell
import { vl } from "@vega/vega-lite-api-v5"
Insert cell
Insert cell
import {buildURI} from "@weiglemc/using-the-soda-api-to-access-data-from-the-virginia-open-data"
Insert cell
uri = buildURI("p2ww-25u5")
Insert cell
raw_data = (await fetch(uri)).json()
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