Public
Edited
Oct 26, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vl.markSquare({size: 2, opacity: 1})
.data('data/zipcodes.csv')
.transform(vl.calculate('substring(datum.zip_code, 0, 1)').as('digit'))
.project(
vl.projection('albersUsa')
)
.encode(
vl.longitude().fieldQ('longitude'),
vl.latitude().fieldQ('latitude'),
vl.color().fieldN('digit')
)
.width(width)
.height(Math.floor(width / 1.75))
.autosize({type: 'fit-x', contains: 'padding'})
.config({view: {stroke: null}})
.render()
Insert cell
Insert cell
{
const brush = vl.selectInterval().encodings('x');
const click = vl.selectPoint().encodings('color');

const scale = {
domain: ['sun', 'fog', 'drizzle', 'rain', 'snow'],
range: ['#e7ba52', '#a7a7a7', '#aec7e8', '#1f77b4', '#9467bd']
};

const plot1 = vl.markPoint({filled: true})
.encode(
vl.color().value('lightgray')
.if(brush, vl.color().fieldN('weather').scale(scale).title('Weather')),
vl.size().fieldQ('precipitation').scale({domain: [-1, 50], range: [10, 500]}).title('Precipitation'),
vl.order().fieldQ('precipitation').sort('descending'),
vl.x().timeMD('date').axis({title: 'Date', format: '%b'}),
vl.y().fieldQ('temp_max').scale({domain: [-5, 40]}).axis({title: 'Maximum Daily Temperature (°C)'})
)
.width(width)
.height(300)
.params(brush)
.transform(vl.filter(click));

const plot2 = vl.markBar()
.encode(
vl.color().if(click, vl.color().fieldN('weather')).value('lightgray')
.scale(scale).title('Weather'),
vl.x().count(),
vl.y().fieldN('weather').scale({domain: scale.domain}).title('Weather')
)
.width(width)
.params(click)
.transform(vl.filter(brush));

return vl.vconcat(plot1, plot2)
.data('data/seattle-weather.csv')
.autosize({type: 'fit-x', contains: 'padding'})
.render();
}
Insert cell
Insert cell
vl.markBar({ opacity: 0.4 })
.params(
vl.param('Year').value(2000).bind(vl.slider(1850, 2000, 10))
)
.data('data/population.json')
.transform(
vl.calculate('datum.sex === 1 ? "Male" : "Female"').as('sex'),
vl.filter('datum.year === Year')
)
.encode(
vl.x().sum('people').scale({ domain: [0, 12e6] }).stack(null).title('People'),
vl.y().fieldO('age').sort('descending').title('Age'),
vl.color().fieldN('sex').scale({ range: ['#675193', '#ca8861'] }).title('Sex')
)
.height(300) // fix the height to keep stability over missing data
.render()
Insert cell
Insert cell
Insert cell
viewof year = Range([1850, 2000], { step: 10, value: 2000 })
Insert cell
vl.markBar({ opacity: 0.4 })
.params(
// use viewof to bind to the input element (the view), not the numeric year value
vl.param('Year').bind(viewof year)
)
.data('data/population.json')
.transform(
vl.calculate('datum.sex === 1 ? "Male" : "Female"').as('sex'),
vl.filter('datum.year === Year')
)
.encode(
vl.x().sum('people').scale({ domain: [0, 12e6] }).stack(null).title('People'),
vl.y().fieldO('age').sort('descending').title('Age'),
vl.color().fieldN('sex').scale({ range: ['#675193', '#ca8861'] }).title('Sex')
)
.height(300)
.render()
Insert cell
Insert cell
{
const isOrigin = vl.selectPoint('isOrigin')
.fields('Origin')
.bind('legend'); // bind to legend interactions
const isYear = vl.selectPoint('isYear')
.fields('Year').value(1970)
.bind(vl.slider(1970, 1980, 1).name('Year')); // bind to slider
const show = vl.and(isOrigin, isYear); // combine selections

return vl.markCircle()
.data('data/cars.json')
.transform(
vl.calculate('year(datum.Year)').as('Year')
)
.params(isOrigin, isYear) // add selections to plot
.encode(
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.color().if(show, vl.color().fieldN('Origin')).value('grey'),
vl.opacity().if(show, vl.value(1.0)).value(0.2)
)
.render();
}
Insert cell
Insert cell
Insert cell
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