Published
Edited
Apr 30, 2021
3 forks
9 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
cars = (await require('vega-datasets@1'))['cars.json']()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vl.markPoint({filled:true, color:'teal'})
.data(cars)
.encode(
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.tooltip('Name') // New!
)
.render()
Insert cell
Insert cell
vl.markPoint({filled:true, color:'teal'})
.data(cars)
.encode(
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.tooltip(['Name', 'Origin']) // New!
)
.render()
Insert cell
Insert cell
Insert cell
{
// The selection instance stores our selected points, and we can use this to do conditional encodings later.
const selection = vl.selectPoint();
return vl.markPoint({filled:true})
.data(cars)
.encode(
vl.color().value('teal'), // same effect as putting color in the markPoint({...})
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon')
)
// Use params() method to say
// "the 'selection' should be invoked, please let me interact with the graph by the type in selection!"
.params(selection)
.render()
}
Insert cell
Insert cell
{
const selection = vl.selectPoint();
return vl.markPoint({filled:true})
.data(cars)
.encode(
vl.color().value('teal'),
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.opacity().if(selection).value(0.1) // New!
)
.params(selection)
.render()
}
Insert cell
Insert cell
{
const selection = vl.selectPoint();
return vl.markPoint({filled:true})
.data(cars)
.encode(
vl.color().if(selection, vl.value('teal')).value("gray"), // New!
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.opacity().if(selection).value(0.1)
)
.params(selection)
.render()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {uniqueValid} from '@uwdata/data-utilities'
Insert cell
Insert cell
origin = uniqueValid(cars, d => d.Origin)
Insert cell
Insert cell
{
const selection = vl.selectPoint('Cars') // name the selection 'Cars' (what will happen if we delete 'Cars'?)
.fields('Origin') // limit selection to the Origin field
.init(origin[0]) // use first genre entry as initial value
.bind(vl.menu(origin)); // bind to a menu of unique genre values
// Nothing changed below
return vl.markPoint({filled:true})
.data(cars)
.params(selection)
.encode(
vl.color().if(selection, vl.value('teal')).value("gray"),
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.opacity().if(selection).value(0.1)
)
.render()
}
Insert cell
Insert cell
{
const selection = vl.selectPoint('Cars')
.fields('Origin')
.init(origin[0])
.bind(vl.radio(origin)); // New!

// Nothing changed below
return vl.markPoint({filled:true})
.data(cars)
.params(selection)
.encode(
vl.color().if(selection, vl.value('teal')).value("gray"),
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.opacity().if(selection).value(0.1)
)
.render()
}
Insert cell
Insert cell
Insert cell
Insert cell
cylinders = uniqueValid(cars, d => d.Cylinders)
Insert cell
{ const selection = vl.selectPoint('Cars')
.fields('Origin', 'Cylinders') // New!
.init({Origin: origin[2], Cylinders: cylinders[3]}) // New! Notice what we have for initial values.
.bind({Origin: vl.menu(origin).name("Origin"), Cylinders: vl.slider(3, 8, 1).name("Cylinders")}); // New!

return vl.markCircle()
.data(cars)
.params(selection)
.encode(
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.color().if(selection, vl.fieldN('Origin')).value('grey'),
vl.opacity().if(selection, vl.value(0.8)).value(0.1)
)
.render()
}
Insert cell
Insert cell
{
const isOrigin = vl.selectPoint('isOrigin')
.fields('Origin')
.bind('legend'); // bind to legend interactions
const numCylinders = vl.selectPoint('Cars')
.fields('Cylinders')
.init(cylinders[3])
.bind(vl.slider(3, 8, 1).name("Cylinders"));
const show = vl.and(isOrigin, numCylinders); // combine selections

return vl.markCircle()
.data(cars)
.params(isOrigin, numCylinders) // 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
year_slider = Range([1970, 1980], { step: 1, value: 1970 })
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const brush = vl.selectInterval() // Brush is a better (vivid?) name than selection in this case!
.encodings('x'); // limit selection to x-axis (year) values
// dynamic query histogram
const years = vl.markBar()
.data(cars)
.params(brush) // params(brush) assure that we are able to drag on the bar chart!
.encode(
vl.x().year('Year'),
vl.y().count().title(null)
)
.width(390)
.height(60)

const scatter = vl.markPoint({filled:true})
.data(cars)
.encode(
vl.color().fieldN('Origin')
.scale({scheme: 'tableau20'})
.legend({orient: 'bottom', titleOrient: 'left'}),
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon'),
vl.opacity().if(brush, vl.value(0.75)).value(0.05), // Use brush for conditional encodings
vl.tooltip('Name')
)
.width(390)
.height(300);

return vl.vconcat(years, scatter).spacing(5).render();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
return vl.markCircle()
.data(cars)
.encode(
vl.x().fieldQ(vl.repeat('column')),
vl.y().fieldQ(vl.repeat('row')),
vl.color().fieldO('Cylinders'),
vl.opacity().value(0.8)
)
.width(140)
.height(140)
.repeat({
column: ['Acceleration', 'Horsepower', 'Miles_per_Gallon'],
row: ['Miles_per_Gallon', 'Horsepower', 'Acceleration']
})
.render();
}
Insert cell
Insert cell
{
const brush = vl.selectInterval() // create a constant brush
.resolve('global'); // resolve all selections to a single global instance
return vl.markCircle()
.data(cars)
.params(brush) // add selection
.encode(
vl.x().fieldQ(vl.repeat('column')),
vl.y().fieldQ(vl.repeat('row')),
vl.color().fieldO('Cylinders'),
vl.opacity().value(0.8)
)
.width(140)
.height(140)
.repeat({
column: ['Acceleration', 'Horsepower', 'Miles_per_Gallon'],
row: ['Miles_per_Gallon', 'Horsepower', 'Acceleration']
})
.render();
}
Insert cell
Insert cell
{
const brush = vl.selectInterval()
.resolve('global');
return vl.markCircle()
.data(cars)
.params(brush)
.encode(
vl.x().fieldQ(vl.repeat('column')),
vl.y().fieldQ(vl.repeat('row')),
vl.color().if(brush, vl.fieldO('Cylinders')).value('grey'), // New!
vl.opacity().if(brush, vl.value(0.8)).value(0.1) // New!
)
.width(140)
.height(140)
.repeat({
column: ['Acceleration', 'Horsepower', 'Miles_per_Gallon'],
row: ['Miles_per_Gallon', 'Horsepower', 'Acceleration']
})
.render();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vl.markPoint({filled:true, color:'teal'})
.data(cars)
.params(
vl.selectInterval().bind('scales') // Just adding a line of code, how amazing!
)
.encode(
vl.x().fieldQ('Horsepower'),
vl.y().fieldQ('Miles_per_Gallon')
)
.render()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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