Public
Edited
Jan 6, 2024
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
or using the new Markdown mode of Observable:
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
'hello cell'
Insert cell
Insert cell
Insert cell
currentWeek = 2
Insert cell
"There are " + (10 - currentWeek) + " weeks left in the quarter"
Insert cell
Insert cell
{
const course = "CSE442";
const message = "Welcome to " + course;
return message;
}
Insert cell
Insert cell
viewof slider = html`<input type="range" value=42 min=0 max=100 step=1></input>`
Insert cell
Insert cell
tex`f(x) = x^2 \rightarrow f(${slider}) = ${slider}^2 = ${slider * slider}`
Insert cell
Insert cell
blockOutput = {
const myConstant = '_How do I love thee?_ Let me count the ways: ';
let myVariable = [];
// you didn't think you'd make it to the end without a for loop, did you?
for (let i = 0; i < 3; ++i) {
// push adds an element to an array, updating it in place
myVariable.push(`**${i + 1}...**`);
}
// you can use tagged templates anywhere!
return md`${myConstant + myVariable.join(' ')}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
442 // a number
Insert cell
{
let number = 442;
return number;
}
Insert cell
"Data Visualization" // a string
Insert cell
true // a boolean
Insert cell
isNaN(442) // you may use isNaN(a) to check if a is Not-A-Number
Insert cell
(1 + Math.sqrt(5)) / 2 // you can also do math
Insert cell
Math.random() // or generate 'random' numbers
Insert cell
2 < 1 // you can compare things
Insert cell
"A" < "a" // including string comparisons
Insert cell
2 + 2 === 4 // more comparison
Insert cell
2 + 2 !== "4" // and more
Insert cell
Insert cell
2 + 2 == "4" // double equals
Insert cell
2 + 2 === "4" // triple equals
Insert cell
Insert cell
Insert cell
date = new Date()
Insert cell
Insert cell
Insert cell
Insert cell
function addMe(a, b) { // function signature: name and input arguments
return a + b; // function body, with return statement for output
}
Insert cell
Insert cell
addMe(2, 2)
Insert cell
addMe('data', ' visualization')
Insert cell
addMe('💕', 'U', '😍') // sorry heart-eyes, extra arguments are ignored
Insert cell
Insert cell
addMe('1') // something from nothing
Insert cell
addMe()
Insert cell
Insert cell
addMe2 = (a, b) => a + b
Insert cell
Insert cell
Insert cell
{
const demo = {
soul: 'd3',
callback: function() {
return this },
}

return demo.callback()
}
Insert cell
Insert cell
{
const demo = {
soul: 'd3',
callback: () => this,
}
return demo.callback()
}
Insert cell
Insert cell
Insert cell
Insert cell
{
console.log("Date now: " + Date.now());
for (let i = 0; i < 10; i++){
console.log(i);
}
return "example cell";
}
Insert cell
Insert cell
Insert cell
Insert cell
arr1 = [1, 2, 3, 'hi'] // you can initialize an array like this
Insert cell
arr1.length
Insert cell
arr1[0]
Insert cell
arr1.slice(1, 3)
Insert cell
{
arr1.push('Husky'); // you can push elements to array, this updates the array content
return arr1;
}
Insert cell
Insert cell
Insert cell
arr1.map(d => d * 2)
Insert cell
Insert cell
result = arr1.filter(d => !isNaN(d)).map(d => d * 2) // keep valid numbers only, then double them
Insert cell
result.slice().sort() // the default sort method is ascending
Insert cell
result
.slice() // you can first make a copy of an array, so we don't overwrite earlier values
.sort((a, b) => b - a) // you can define a custom sort comparator; here we sort numbers in descending order
Insert cell
Insert cell
Insert cell
object = ({key: "value", anotherKey: "anotherValue"})
Insert cell
Insert cell
Insert cell
object['key'] = 'new Value'
Insert cell
object['newKey'] = 'new value'
Insert cell
Object.keys(object) // return an array of property key strings
Insert cell
Object.values(object) // return an array of property values
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
csvText = FileAttachment("schedule-OH.csv").text() // loading a text file attached in Observable
Insert cell
dataCSV = d3.csvParse(csvText) // if we have the text loaded already, we can use d3.csvParse
Insert cell
csvURL = FileAttachment("schedule-OH.csv").url() // you can get the url of a file you attached to Observable with .url()
Insert cell
dataCSV2 = d3.csv(csvURL) // if we have a URL to a CSV, we can use d3.csv to both load and parse
Insert cell
Insert cell
auto = d3.csv(csvURL, d3.autoType) // can handle numbers and booleans, but not all date formats
Insert cell
manual = d3.csv(csvURL, ({Name, Job, date}) => ({Name: Name, Job: Job, 'OH Date': new Date(date)}))
Insert cell
datee = manual[1]['OH Date'].getDay()
Insert cell
Insert cell
Insert cell
FileAttachment("schedule-OH.json").text() // here's what JSON data looks like as text
Insert cell
dataJSON = FileAttachment("schedule-OH.json").json() // load and parse JSON from a file attached in Observable
Insert cell
json_url = FileAttachment("schedule-OH.json").url() // we can also get a URL for a file attachment
Insert cell
dataJSON2 = d3.json(json_url) // loading with url
Insert cell
Insert cell
strJson = JSON.stringify(dataJSON)
Insert cell
JSON.parse(strJson)
Insert cell
Insert cell
Insert cell
Insert cell
// your code goes here
// uncomment cell below to see the solution

Insert cell
{ // solution:
return data.filter(d => d['Job'] ==='TA').sort((a, b) => a["Name"] > b["Name"] ? 1 : -1)
}
Insert cell
Insert cell
// your code goes here
// uncomment cell below to see the solution

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dt = aq.table({
u: ['a', 'a', 'b', 'b'],
x: Int32Array.of(1, 2, 3, 4),
y: Float64Array.of(5, 6, 7, 8)
})
Insert cell
Insert cell
dt.view()
Insert cell
Insert cell
[dt.numCols(), dt.numRows()]
Insert cell
dt.columnNames()
Insert cell
dt.get("y", 2)
Insert cell
dt.array('y')
Insert cell
Insert cell
dt.objects()
Insert cell
Insert cell
viewof beers = aq // viewof shows the table view, but assigns the table value
.fromCSV(await FileAttachment('beer.csv').text())
.view({ height: 240 }) // set maximum height of table viewer in pixels
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
beers
.orderby('abv')
.view(5) // shorthand for view({ limit: 5 })
Insert cell
Insert cell
beers
.orderby('style', aq.desc('abv'))
.view(50)
Insert cell
Insert cell
Insert cell
Insert cell
beers
.orderby(aq.desc('abv'))
.select('name', 'style', 'abv') // ['name', 'style', 'abv'] also works
.view(5)
Insert cell
Insert cell
Insert cell
Insert cell
beers
.filter(d => op.includes(op.lower(d.name), 'hop'))
.view()
Insert cell
Insert cell
Insert cell
Insert cell
beers
.derive({ intensity: d => 3 * d.abv + op.log10(d.ibu) / 3 })
.orderby(aq.desc('intensity'))
.view(10)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
beers
.rollup({
mean_abv: d => op.mean(d.abv), // op.average is available as a synonym
mean_ibu: d => op.mean(d.ibu),
mean_intensity: d => op.mean(3 * d.abv + op.log10(d.ibu) / 3),
corr_abv_ibu: d => op.corr(d.abv, d.ibu),
count: d => op.count()
})
.view()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
beers
.groupby('style')
.rollup({
mean_abv: d => op.mean(d.abv),
mean_ibu: d => op.mean(d.ibu),
mean_intensity: d => op.mean(3 * d.abv + op.log10(d.ibu) / 3),
count: op.count()
})
.filter(d => d.count > 20) // let's not trust results with little support...
.orderby(aq.desc('mean_intensity'))
.view(10)
Insert cell
Insert cell
Insert cell
beers
.groupby('style')
.derive({ intensity: d => 3 * d.abv + op.log10(d.ibu) / 3 })
.derive({ zscore: ({ intensity: x }) => (x - op.mean(x)) / op.stdev(x) || 0 })
.orderby(aq.desc('zscore'))
.filter(d => op.rank() === 1 && op.count() > 20) // filter by rank and count
.select(aq.not('brewery_id', 'intensity'))
.view({ height: 400 }) // set max height to show full table without scroll
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof breweries = aq
.fromCSV(await FileAttachment('breweries.csv').text())
.view(10)
Insert cell
beers
.join(breweries)
.view(5)
Insert cell
Insert cell
beers
.join(breweries, ['brewery_id', 'brewery_id']) // <- just 'brewery_id' also works!
.view(5)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
beers
.view(5)
Insert cell
Insert cell
beers
.fold(["abv", "ibu"])
.view(5)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
beers
.pivot(
{style : d => d.style},
{avg_ibu : d => op.mean(d.ibu)}
).view(5)
Insert cell
Insert cell
beers
.fold(["abv", "ibu"])
.pivot(
{key : d => d.key},
{value : d => op.mean(d.value)}
)
.view()
Insert cell
Insert cell
Insert cell
cars = (await require('vega-datasets@1'))['cars.json']()
Insert cell
Insert cell
viewof cars_table = aq.from(cars).view()
Insert cell
Insert cell
// to be filled -- filter only USA.
// op.upper(): Returns the string value converted to upper case.
// op.includes(array, value[, index]): Determines whether an array includes a certain value among its entries, returning true or false as appropriate.
Insert cell
// Shengqi's solution:
cars_table
// .filter(d => op.includes(op.upper(d.Origin), 'USA'))
.filter(d => op.upper(d.Origin) === "USA")
.view()
Insert cell
Insert cell
// to be filled -- filter and get the highest mpg in the USA.

Insert cell
// Shengqi's solution:
cars_table
.filter(d => op.includes(op.upper(d.Origin), 'USA'))
// .filter(d => op.upper(d.Origin) === "USA")
.orderby(aq.desc("Miles_per_Gallon"))
.view()

// Answer: plymouth champ
Insert cell
Insert cell
// to be filled -- filter for cars only made from USA, sort in decending order, and select a subset of collumn to show for 5 rows only.

Insert cell
// Shengqi's solution:
cars_table
.filter(d => op.includes(op.upper(d.Origin), 'USA'))
// .filter(d => op.upper(d.Origin) === "USA")
.orderby(aq.desc("Miles_per_Gallon"))
.select(["Name", "Miles_per_Gallon", "Horsepower", "Year", "Origin"])
.view(5)

// Answer: plymouth champ
Insert cell
Insert cell
Insert cell
Insert cell
// to be filled -- find answer for each region

Insert cell
// Shengqi's answer
// 1) Which origin has the most cars in this dataset? How many cars each origin produced?
cars_table
.groupby("Origin")
.rollup({
count: op.count()
})
.orderby(aq.desc("count"))
.view()
Insert cell
// Shengqi's answer
// 2) What is the median number for cylinders in each region?
cars_table
.groupby("Origin")
.rollup({
median_cylinders: d => op.median(d.Cylinders),
count: op.count()
})
.orderby(aq.desc("count"))
.view()
Insert cell
// Shengqi's answer
// 3) What is the min and max year in each region?
cars_table
.groupby("Origin")
.rollup({
min_year: d => op.min(d.Year),
max_year: d => op.max(d.Year),
median_cylinders: d => op.median(d.Cylinders),
count: op.count()
})
.orderby(aq.desc("count"))
.view()
Insert cell
// Shengqi's answer
// 4) What are the mean (average) values of miles per gallons, displacement, horsepower, weight, and acceleration in each region?
cars_table
.groupby("Origin")
.rollup({
mean_mpg: d => op.mean(d.Miles_per_Gallon),
mean_displacement: d => op.mean(d.Displacement),
mean_horsepower: d => op.mean(d.Horsepower),
mean_weight: d => op.mean(d.Weight_in_lbs),
mean_acc: d => op.mean(d.Acceleration),
min_year: d => op.min(d.Year),
max_year: d => op.max(d.Year),
median_cylinders: d => op.median(d.Cylinders),
count: op.count()
})
.orderby(aq.desc("count"))
.view()
Insert cell
Insert cell
// to be filled -- change the unit for the weights
Insert cell
// Shengqi's answer
// 5) Add a new column for weight in kg system.
cars_table
.derive({ Weight_in_kg: d => 0.453592 * d.Weight_in_lbs })
.orderby(aq.desc("Weight_in_kg"))
.view()

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