Published
Edited
Apr 19, 2022
2 stars
Insert cell
Insert cell
Insert cell
data = FileAttachment("bandcamp-oneday.csv").csv({ typed: true })
Insert cell
Inputs.table(data)
Insert cell
data[0]
Insert cell
viewof index = Inputs.range([0, data.length-1], { step: 1, value: 0, label: "index"})
Insert cell
data[index]
Insert cell
import {SummaryTable} from "@observablehq/summary-table"
Insert cell
SummaryTable(data)
Insert cell
Insert cell
sample = data.slice(0,100)
Insert cell
Plot.dot(sample, { x: "utc_timestamp", y: "amount_paid" }).plot()
Insert cell
Plot.plot({
marks: [
Plot.dot(sample, {x: "utc_timestamp", y: "amount_paid", fill: "blue"}),
Plot.dot(sample, {x: "utc_timestamp", y: "item_price", stroke: "orange"}),
]
})
Insert cell
Plot.plot({
marks: [
Plot.dot(sample, {x: "utc_timestamp", y: "item_price", stroke: "orange"}),
Plot.arrow(sample, { x1: "utc_timestamp", y1: "item_price", x2: "utc_timestamp", y2: "amount_paid" })
]
})
Insert cell
Plot.dot(sample, {
x: "utc_timestamp",
y: d => d.amount_paid - d.item_price,
}).plot()
Insert cell
Plot.dot(sample, {
x: "utc_timestamp",
y: d => d.amount_paid - d.item_price,
fill: d => d.amount_paid - d.item_price,
stroke: "gray"
}).plot({
color: { scheme: "greens" }
})
Insert cell
Plot.dot(sample, {
x: "utc_timestamp",
y: d => d.amount_paid - d.item_price,
stroke: d => d.amount_paid - d.item_price > 0
}).plot({
color: { range: ["orange", "steelblue"] }
})
Insert cell
Plot.barX(data, Plot.groupY({x: "mean"}, {
x: "amount_paid",
y: "type",
}))
.plot({ marginLeft: 100 })
Insert cell
Plot.barX(data, Plot.groupY({x: "mean"}, {
x: "amount_paid",
y: "type",
sort: { y: "x", reverse: true, limit: 3 }
}))
.plot({ marginLeft: 100 })
Insert cell
Plot.rectY(data, Plot.binX({y: "count"}, {
x: d => d.amount_paid - d.item_price,
thresholds: 40
})).plot({ grid: true })
Insert cell
Plot.plot({
marks: [
Plot.rectY(data, Plot.binX({y: "sum"}, { x: "utc_timestamp", y: "amount_paid", fill: "type", thresholds: d3.utcHour }))
],
})
Insert cell
Insert cell
viewof groupby = Inputs.select(["type", "country"], {label: "group by"})
Insert cell
viewof aggregate = Inputs.radio(["mean", "sum"], {label: "aggregate", value: "mean"})
Insert cell
// let's update this code to change the group by and the aggregation
Plot.barX(data, Plot.groupY({x: aggregate}, {
x: "amount_paid",
y: groupby,
sort: { y: "x", reverse: true, limit: 10 }
}))
.plot({
caption: `${aggregate} amount paid by ${groupby}`,
x: { label: `${aggregate} amount_paid`},
marginLeft: 100
})
Insert cell
data.map(d => d.country)
Insert cell
countries = new Set(data.map(d => d.country))
Insert cell
viewof country = Inputs.select(countries, {label: "Select one"})
Insert cell
// let's update this code to change the group by and the aggregation
Plot.barX(data.filter(d => d.country == country), Plot.groupY({x: "sum"}, {
x: "amount_paid",
y: "type",
sort: { y: "x", reverse: true, limit: 10 }
}))
.plot({
marginLeft: 100
})
Insert cell
viewof range = Inputs.range([0, 100], {label: "Amount", step: 1})
Insert cell
// lets update this code to color dots differently above and below a minimum amount paid
Plot.plot({
marks: [
Plot.dot(data, {
x: "utc_timestamp",
y: "amount_paid",
fill: d => d.amount_paid > range,
r: d => d.amount_paid > range,
fillOpacity: d => d.amount_paid > range,
}),
Plot.ruleY([range], { stroke: "orange" })
],
y: { type: "log" },
r: { range: [ 2, 3 ] },
opacity: { range: [0.25, .7 ] },
color: { range: [ "orange", "steelblue"] }
})
Insert cell
Insert cell
Inputs.table(search)
Insert cell
chart = Plot.plot({
marks: [
Plot.rectY(search, Plot.binX({y: "sum"}, { x: "utc_timestamp", y: "amount_paid", fill: "type", thresholds: d3.utcHour }))
],
marginLeft: 100
})
Insert cell
chart.scale("color")
Insert cell
chart.scale("x")
Insert cell
Insert cell
import { Treemap } from "@d3/treemap"
Insert cell
Treemap(d3.rollup(data, v => v.length, d => d.country), {
value: d => d[1],
label: d => d[0]
})
Insert cell
rolled = d3.rollup(data, v => {
return {
count: v.length,
total_paid: d3.sum(v, o => o.amount_paid),
type: v[0].type
}},
d => d.type)
Insert cell
treemap = Treemap(rolled, {
value: d => d[1].count,
group: d => d[1].type,
label: d => d[1].type,
title: d => `${d[1].type} ${d[1].count}`,
fillOpacity: 1
})
Insert cell
Plot.legend({
color: {
domain: treemap.scales.color.domain(),
range: treemap.scales.color.range()
},
legend: "swatches"
})
Insert cell
import { BubbleChart } from "@d3/bubble-chart"
Insert cell
BubbleChart(rolled, {
value: d => d[1].count,
group: d => d[1].type,
label: d => d[1].type,
title: d => `${d[1].type} ${d[1].count}`,
})
Insert cell
import { BarChart } from "@d3/bar-chart-transitions"
Insert cell
bardata = Array.from(rolled.values())
Insert cell
chart2 = BarChart(bardata, {
x: d => d.type,
y: d => d.count,
xDomain: typelist,
width: 600,
height: 400,
color: "steelblue",
duration: 750 // slow transition for demonstration
})
Insert cell
viewof country2 = Inputs.select(new Set(data.map(d => d.country)), { label: "Select country:" })
Insert cell
bycountry = d3.rollup(data.filter(d => d.country == country2),
v => {
return {
count: v.length,
type: v[0].type
}},
d => d.type
)
Insert cell
chart2.update(Array.from(bycountry.values()), { xDomain: typelist })
Insert cell
// we will end up wanting to keep the order of the x domain the same
typelist = ["bundle", "merch", "track", "album"]
Insert cell
Insert cell
<svg width=940 height=300>
<rect x=250 y=50 width=200 height=50 fill="orange"></rect>
<circle cx=100 cy=100 r=50 fill="seagreen"></circle>
<g transform="translate(250,50)rotate(-10)">
<path d="M50,50 L200,50 L300,100" stroke="black" stroke-width=10 fill="none"></path>
<text x="50" y="40">Hello, world!</text>
<g>
</svg>
Insert cell
import { Scatterplot, AnimatedScatterplot, BrushScatterplot} from "@observablehq/workshop-itdvpd-d3-essentials"
Insert cell
Scatterplot(data.filter(d => d.country == "Netherlands"), {
x: d => d.utc_timestamp,
y: d => d.amount_paid,
xType: d3.scaleTime
})
Insert cell
chart3 = AnimatedScatterplot(data.filter(d => d.country == "Netherlands"), {
x: d => d.utc_timestamp,
y: d => d.amount_paid,
xType: d3.scaleTime
})
Insert cell
viewof country3 = Inputs.select(new Set(data.map(d => d.country)), { label: "select a country", value: "Netherlands" })
Insert cell
chart3.update(data.filter(d => d.country == country3))
Insert cell
viewof brushed = BrushScatterplot(data.filter(d => d.country == "Netherlands"), {
x: d => d.utc_timestamp,
y: d => d.amount_paid,
xType: d3.scaleTime
})
Insert cell
Inputs.table(brushed)
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