Notebooks 2.0 is here.

Public
Edited
Sep 11, 2023
Insert cell
Insert cell
Insert cell
iris = require('@observablehq/iris')
Insert cell
Inputs.table(iris)
Insert cell
Insert cell
Insert cell
Insert cell
Wrangler(iris)
Insert cell
avgPetalLen = aq.from(iris)
.select('petalLength','species')
.groupby('species')
.rollup({mean:d => op.mean(d["petalLength"])})
.objects() // return an array of objects
Insert cell
Insert cell
Insert cell
groupbySpec = Object.fromEntries(d3.group(iris, d => d.species))
Insert cell
/*
//pure js solution to above - no d3 - same result
groupbySpec = iris.reduce((obj, v, index, a, key = (d=>d.species)(v) ) => ((obj[key] || (obj[key] = [])).push(v), obj), {});
*/
Insert cell
Insert cell
avgPetalLen_Alt1 = Object.keys(groupbySpec).map(function (k) {
return {
"species": k,
"mean": d3.mean(groupbySpec[k], d=> d.petalLength)
}
})
Insert cell
/*
// the following pure js reducer can also find the mean - but avg will be slightly off - d3 handles floaing points numbers more accurately

groupbySpec[k].reduce((accumulator, currentValue, index, array) => {
return accumulator += currentValue.petalLength / array.length
}, 0)
*/
Insert cell
Insert cell
Insert cell
rollup = d3.rollup(iris, v => d3.mean(v, d => d.petalLength), d => d.species)
Insert cell
Insert cell
rollupobj = Object.fromEntries(rollup)
Insert cell
Insert cell
avgPetalLen_Alt2 = Object.keys( rollupobj ).map(function (o) {
return {
"species": o,
"mean": rollupobj[o]
}
})
Insert cell
Insert cell
Insert cell
Chart = require('chart.js');
Insert cell
{
//find unique species
const spec = [... new Set(iris.map(d => d.species))]
//create color palette for each spec
let colors = [];
spec.forEach(s => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
const color = `rgb(${r}, ${g}, ${b})`;
colors.push(color)
})

//Chart.js supports various structures and multiple data sets. Has the ability to map object properties to axes. https://www.chartjs.org/docs/latest/general/data-structures.html
const data = {
datasets: [
{
data: avgPetalLen, //or avgPetalLen_Alt1, avgPetalLen_Alt2
parsing: {
xAxisKey: 'species',
yAxisKey: 'mean'
},
backgroundColor: colors, //must be color or array of colors (tied to axis)
}
]
};

const config = {
type: 'bar',
data: data,
options: {
plugins: { //extra customization
legend: false, //default is true
title: { //default false
display: true,
text: 'Petal Length by Iris Species',
font: {
size: 32,
//try family, weight
}
},
},
scales: {
y: {
beginAtZero: true, //set at 0
ticks: {
// Include measurement type on ticks
callback: function(value, index, values) {
return value + ' cm';
}
}
},
},
},
};
//clear existing canvas if Observable block is ran
// if ( document.getElementById('bar')){
// document.getElementById('bar').remove()
// }
let canvas = document.createElement('canvas')
canvas.id = "bar"
let chart = new Chart(
canvas,
config
);

//return canvas element to Observable
return canvas
}

Insert cell
Insert cell
Insert cell
avgPetalWidth = aq.from(iris)
.select('petalWidth','species')
.groupby('species')
.rollup({mean:d => op.mean(d["petalWidth"])})
.objects() // Uncomment to return an array of objects
Insert cell
{
const data = {
datasets: [
{
type: "bar",
label: "Petal Length",
data: avgPetalLen, //or avgPetalLen_Alt1, avgPetalLen_Alt2
parsing: {
xAxisKey: 'species',
yAxisKey: 'mean'
},
backgroundColor: "red",
order: 2
},
{
type: "bar", //try "line"
label: "Petal Width",
data: avgPetalWidth, //or avgPetalLen_Alt1, avgPetalLen_Alt2
parsing: {
xAxisKey: 'species',
yAxisKey: 'mean'
},
backgroundColor: "blue",
order: 1 //one is closer
}
]
};

const config = {
data: data,
options: {
scales: {
y: {
beginAtZero: true, //set at 0
ticks: {
// Include measurement type on ticks
callback: function(value, index, values) {
return value + ' cm';
}
}
},
},
plugins: {
legend: {
labels: {
font: {
size: 16,
}
}
}
},
},
};
//clear existing canvas if Observable block is ran
if ( document.getElementById('mixed')){
document.getElementById('mixed').remove()
}
let canvas = document.createElement('canvas')
canvas.id = "mixed"
let chart = new Chart(
canvas,
config
);

//return canvas element to Observable
return canvas
}
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