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

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