Public
Edited
Jun 23, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// arquero is a lot like dplyr + tidyr
// this import command is pulling in a notebook that defines a bunch of these functions
// you could also do require('arquero') which is more like R's library
import {aq, op} from '@uwdata/arquero'
Insert cell
// vega-lite is similar to ggplot2
// require is pulling in the package vega-lite
vg = require('vega-lite')
Insert cell
penguins = await aq.loadCSV(
'https://gist.githubusercontent.com/slopp/ce3b90b9168f2f921784de84fa445651/raw/4ecf3041f0ed4913e7c230758733948bc561f434/penguins.csv'
)
Insert cell
viewof cr_proj_aq = aq // viewof shows the table view, but assigns the table value
.fromCSV(await FileAttachment('20230616 casino revenue expenditures from pub rec req.csv').text())
.view({ height: 240 }) // set maximum height of table viewer in pixels
Insert cell
20230616 casino revenue expenditures from pub rec req@1.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
cr_proj_aq.view()
Insert cell
penguins.view()
Insert cell
// we can do all sorts of dplyr-esq things
// Tip: rollup is like summarize; derive is like mutate
cr_proj_aq
.groupby('Ward')
.filter(p => p.Ward > 0)
.rollup({
count: op.count(),
avg_budget: op.average('Budget')
})
.view()
Insert cell
// we can do all sorts of dplyr-esq things
// Tip: rollup is like summarize; derive is like mutate
penguins
.groupby('species')
.filter(p => p.body_mass_g > 0)
.rollup({
count: op.count(),
avg_mass_g: op.average('body_mass_g')
})
.view()
Insert cell
Insert cell
import { vl } from "@vega/vega-lite-api"
Insert cell
vl
.markPoint() // the first two lines are akin to ggplot(data = penguins) + geom_point
.data(penguins)
.encode( // encode is like aes
vl.x().fieldQ('body_mass_g') // aes(x = body_mass_g)
.scale({domain: [2000, 6500]}) // modify scale attributes, similar to scale_x_axis
.axis({title: "Mass (g)"}),
vl.y().fieldQ('bill_length_mm')
.scale({domain: [30, 60]}),
vl.color().fieldN('species'),
vl.tooltip(['species', 'sex', 'year', 'island']) // tooltips for free!
).render()
Insert cell
Insert cell
Insert cell
// This step is like a library command
d3 = require('d3')
Insert cell
// this is really the magic, we get to re-use cells from other observable documents as templates,
// over-riding attributes with our own data
import { chart } with { wait_times as data, bins } from "@d3/histogram"
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
// load our data
faithful = await d3.tsv(
'https://gist.githubusercontent.com/curran/4b59d1046d9e66f2787780ad51a1cd87/raw/9ec906b78a98cf300947a37b56cfe70d01183200/data.tsv'
)
Insert cell
// this is probably the weirdest part for R users
// think about it like purrr:::map_dbl(faithful, ~.x$eruptions)
wait_times = faithful.map(o => o.eruptions)
Insert cell
// reactivity here is free, we don't have to do input$ to access the reactive value num_bins!
bins = d3.bin().thresholds(num_bins)(wait_times)
Insert cell
Insert cell
// click the pin icon to your left to hide the code that creates our input if you really want the true "shiny app" experience
viewof num_bins = slider({
min: 1,
max: 50,
value: 30,
title: "Number of bins"
})
Insert cell
chart
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