Published
Edited
Dec 3, 2019
Insert cell
Insert cell
{
// create an interval selection over an x-axis encoding
const brush = vl.selectInterval().encodings('x');
// determine opacity based on brush
const opacity = vl.opacity().if(brush, vl.value(0.9)).value(0.1);

// an overview histogram of cars per year
// add the interval brush to select cars over time
const overview = vl.markBar()
.encode(
vl.x().fieldQ('lPer100km') // extract year unit, treat as ordinal
.scale({rangeStep: null}) // subbdivide the full default chart width
.axis({title: null, labelAngle: 0}), // no title, no label angle
vl.y().count().title(null), // counts, no axis title
opacity // modulate bar opacity based on the brush selection
)
.select(brush) // add interval brush selection to the chart
.height(50); // set chart height to 50 pixels
// a detail scatterplot of horsepower vs. mileage
const detail = vl.markPoint()
.encode(
vl.x().fieldT('date'),
vl.y().fieldQ('pricePerL'),
vl.size().fieldQ('lPer100km'),
vl.tooltip().fieldT('date'),
opacity // modulate point opacity based on the brush selection
);

// vertically concatenate (vconcat) charts
return vl.data(fuel).vconcat(overview, detail).render();
}

Insert cell
a4 = d3.tsvParse(await FileAttachment("data.tsv").text(), d3.autoType)
Insert cell
printTable(fuel)
Insert cell
fuel = d3.pairs(
a4.filter(d => d.type === "fuel")
.sort((a, b) => d3.ascending(a.date, b.date)),
(a, b) => ({
...a,
odometer_delta: b.odometer - a.odometer
})
).map(d=>{d.lPer100km = d.amount / d.odometer_delta*100;
d.pricePerL = d.price / d.amount;
return d})
Insert cell
import {vl} from '@vega/vega-lite-api'
Insert cell
import {printTable} from '@uwdata/data-utilities'
Insert cell
d3 = require("d3@^5.13")
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