Public
Edited
Oct 24, 2023
3 forks
9 stars
Insert cell
Insert cell
Insert cell
names = ["joe", "sally", "norbert", "ann", "rafael"]
Insert cell
ages = [32, 13, 14, 22, 76]
Insert cell
d3.zip(names, ages)
Insert cell
Insert cell
Insert cell
Insert cell
preferences = ["ice cream", "juice", "cake"]
Insert cell
d3.zip(names, preferences, ages) // 🌶 we've just lost Ann and Rafael!
Insert cell
Insert cell
Insert cell
d3.transpose([names, ages])
Insert cell
Insert cell
url = "https://api.census.gov/data/2015/acs/acs5?get=B01001_003E,B01001_004E,B01001_005E,B01001_006E,B01001_007E,B01001_008E,B01001_009E,B01001_010E,B01001_011E,B01001_012E,B01001_013E,B01001_014E,B01001_015E,B01001_016E,B01001_017E,B01001_018E,B01001_019E,B01001_020E,B01001_021E,B01001_022E,B01001_023E,B01001_024E,B01001_025E,B01001_027E,B01001_028E,B01001_029E,B01001_030E,B01001_031E,B01001_032E,B01001_033E,B01001_034E,B01001_035E,B01001_036E,B01001_037E,B01001_038E,B01001_039E,B01001_040E,B01001_041E,B01001_042E,B01001_043E,B01001_044E,B01001_045E,B01001_046E,B01001_047E,B01001_048E,B01001_049E&for=us:*"
Insert cell
Insert cell
data = load_data(url) // see the Annex
Insert cell
Insert cell
d3.transpose(data)
Insert cell
Insert cell
map = new Map(d3.transpose(data))
Insert cell
map.get("B01001_022E")
Insert cell
Insert cell
map_numeric = {
const [keys, values] = await load_data(url); // await d3.json(url);
return new Map(d3.zip(keys, Float64Array.from(values)));
}
Insert cell
map_numeric.get("B01001_022E")
Insert cell
Insert cell
d3.transpose(d3.zip(names, ages))
Insert cell
Insert cell
d3.transpose(Array.from(map))
Insert cell
Insert cell
w = width
Insert cell
h = 100
Insert cell
r = (_, i) => 100 + 130 * ((Math.random() * (i % w)) / w)
Insert cell
g = (_, i) => 255 * (1 - (Math.random() * (i % w)) / w)
Insert cell
b = (_, i) => 255 - (Math.random() * 255 * i) / w / h
Insert cell
a = (_, i) => (Math.random() > 0.1 ? 255 : 128)
Insert cell
Insert cell
R = Uint8Array.from({length: w * h}, r)
Insert cell
G = Uint8Array.from({length: w * h}, g)
Insert cell
B = Uint8Array.from({length: w * h}, b)
Insert cell
A = Uint8Array.from({length: w * h}, a)
Insert cell
Insert cell
d3.zip(R, G, B, A) // zip creates an array of arrays…
Insert cell
newData = d3.zip(R, G, B, A).flat() // … that can be flattened to match the canvas ImageData structure
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3-array@3", "d3-fetch@3")
Insert cell
function visual_zip(lists) {
const transposed = d3.transpose(lists); // or d3.zip(...lists)

return svg`<svg width=100% height=${(1.5 + lists.length) *
30} style="text-anchor:middle;dominant-baseline: middle; font: 14px sans-serif">
<defs>
<marker id="arrow"
refX="7" refY="5"
markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10"
orient="auto">
<path d="M0,1L8,5L0,9Z" fill=red />
</marker>
</defs>

<path d="M70,${7 + lists.length * 15} C2,30 2,80 60,${35 +
lists.length * 30}" marker-end="url(#arrow)" stroke=red fill=none />

${lists
.map((things, j) =>
things.map(
(name, i) =>
svg`<g transform="translate(${(i + 1) * 120},${20 +
30 * j})"><text>${name}</text></g>`
)
)
.flat()}

${d3.range(d3.max(lists, d => d.length)).map(
(pair, i) =>
svg`<ellipse transform="translate(${(i + 1) * 120},${7 +
lists.length * 15})" rx=50 ry=${6 + lists.length * 15} stroke='${
i < transposed.length ? "red" : "#aaa"
}' fill=none stroke-dasharray="${i < transposed.length ? "" : "2 5"}" />
`
)}

${transposed.map(
(pair, i) =>
svg`<g transform="translate(${(i + 1) * 120},${35 +
lists.length * 30})"><text>${JSON.stringify(pair).replace(
/"/g,
""
)}</text></g>`
)}
`;
}
Insert cell
// Replaces d3.json(url): the API we call is fragile — for the sake of this tutorial we copied the data inline
function load_data(url) {
return [["B01001_003E","B01001_004E","B01001_005E","B01001_006E","B01001_007E","B01001_008E","B01001_009E","B01001_010E","B01001_011E","B01001_012E","B01001_013E","B01001_014E","B01001_015E","B01001_016E","B01001_017E","B01001_018E","B01001_019E","B01001_020E","B01001_021E","B01001_022E","B01001_023E","B01001_024E","B01001_025E","B01001_027E","B01001_028E","B01001_029E","B01001_030E","B01001_031E","B01001_032E","B01001_033E","B01001_034E","B01001_035E","B01001_036E","B01001_037E","B01001_038E","B01001_039E","B01001_040E","B01001_041E","B01001_042E","B01001_043E","B01001_044E","B01001_045E","B01001_046E","B01001_047E","B01001_048E","B01001_049E","us"],["10175713","10470147","10561873","6447043","4495581","2453321","2400843","6722248","10989596","10625791","9899569","10330986","10571984","11051409","10173646","3730038","5094814","3060112","3816159","4867513","3416432","2378691","2000771","9736305","10031835","10117913","6142996","4268861","2322446","2283357","6422017","10708414","10557848","9956213","10465142","10798384","11474081","10828301","4018137","5572692","3385427","4285748","5720208","4313697","3432738","3937981","1"]];
}
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