Published
Edited
Dec 2, 2019
11 forks
80 stars
Insert cell
Insert cell
// fetch(`https://en.wikipedia.org/w/api.php?format=json&origin=*&action=parse&prop=text&page=List_of_highest-grossing_media_franchises&section=1`).then(response => response.json())
Insert cell
Insert cell
text = FileAttachment("List_of_highest-grossing_media_franchises.json").json()
Insert cell
Insert cell
text.parse.text["*"]
Insert cell
Insert cell
table = {
const parser = new DOMParser();
const external = parser.parseFromString(text.parse.text["*"], "text/html");
const table = document.adoptNode(external.querySelector("table"));
table.style = `
display: block;
position: relative;
max-width: none;
max-height: 600px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
`;
return table;
}
Insert cell
Insert cell
Insert cell
table.querySelector("tbody tr").cloneNode(true)
Insert cell
Insert cell
table.querySelector("tr:not(:first-child)").cloneNode(true)
Insert cell
Insert cell
rows = table.querySelectorAll("tr:not(:first-child)")
Insert cell
names = Array.from(rows, r => r.querySelector("td:nth-child(2)").textContent.trim())
Insert cell
Insert cell
Array.from(rows, r => r.querySelector("td:nth-child(4)").textContent.trim())
Insert cell
Insert cell
+"est. $90 billion"
Insert cell
Insert cell
totalRe = /^(?:est\. )?\$(\d+(?:\.\d+)?) billion/
Insert cell
totalRe.exec("est. $90 billion")
Insert cell
function parseTotal(total) {
const match = totalRe.exec(total);
if (!match) throw new Error("unable to parse total: " + total);
return +`${match[1]}e9`;
}
Insert cell
Insert cell
totals = Array.from(rows, r => parseTotal(r.querySelector("td:nth-child(4)").textContent.trim()))
Insert cell
Insert cell
8.36 * 1e9
Insert cell
Insert cell
+"8.36e9"
Insert cell
Insert cell
parseTotal("est. $100 million") // Error!
Insert cell
Insert cell
vl.markBar()
.data({values: d3.zip(names, totals)})
.encode(
vl.y().fieldN("0").sort(null).axis({title: null}),
vl.x().fieldQ("1").axis({orient: "top", format: "s", title: "Total revenue (est.)"})
)
.width(width)
.autosize({type: "fit-x", contains: "padding"})
.render()
Insert cell
Insert cell
d3.zip(names, totals)
Insert cell
Insert cell
vl.markBar()
.data({values: d3.zip(names, totals)})
.encode(
vl.y().fieldN("0").sort({encoding: "x", order: "descending"}).axis({title: null}),
vl.x().fieldQ("1").axis({orient: "top", format: "s", title: "Total revenue (est.)"})
)
.width(width)
.autosize({type: "fit-x", contains: "padding"})
.render()
Insert cell
Insert cell
breakdowns = Array.from(rows, r => r.querySelector("td:nth-child(5)").textContent.trim())
Insert cell
breakdowns[0]
Insert cell
Insert cell
parseBreakdown(breakdowns[0])
Insert cell
function parseBreakdown(breakdown) {
return breakdown.split(/\n/).map(b => {
const [channel, revenue] = b.split(" – ");
return {channel, revenue};
});
}
Insert cell
Insert cell
revenueRe = /^\$([0-9,]+(?:\.[0-9]+)?)(?:\s(b|m)illion)?/
Insert cell
revenueRe.exec("$61.1 billion[a]")
Insert cell
revenueRe.exec("$520,000[az]")
Insert cell
parseRevenue("$61.1 billion[a]")
Insert cell
parseRevenue("$520,000[az]")
Insert cell
function parseRevenue(revenue) {
const match = revenueRe.exec(revenue);
if (!match) throw new Error("unable to parse revenue: " + revenue);
return +`${match[1].replace(/,/g, "")}e${match[2] === "b" ? 9 : match[2] === "m" ? 6 : 0}`;
}
Insert cell
Insert cell
revenues = Array.from(rows, r => {
const text = r.querySelector("td:nth-child(5)").textContent.trim();
const breakdown = parseBreakdown(text);
return breakdown.map(({channel, revenue}) => {
return {channel, revenue: parseRevenue(revenue)};
});
})
Insert cell
Insert cell
rows[names.findIndex(n => n === "Super Sentai (Power Rangers)")].cloneNode(true)
Insert cell
Insert cell
vl.markBar()
.data({
values: d3.zip(names, revenues).flatMap(([name, revenues]) => {
return revenues.map(({channel, revenue}) => {
return {name, channel, revenue};
});
})
})
.encode(
vl.y().fieldN("name").sort("x").axis({title: null}),
vl.x().fieldQ("revenue").aggregate("sum").axis({orient: "top", format: "s", title: "Revenue (est.)"}),
vl.color().fieldN("channel")
)
.width(width)
.autosize({type: "fit-x", contains: "padding"})
.render()
Insert cell
Insert cell
Insert cell
import {vl} from "@vega/vega-lite-api"
Insert cell
d3 = require("d3-array@2")
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