Public
Edited
Nov 2, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = mat`
- X Y Z
a 0 0 1
b 1 0 1
c 1 1 1
d 1 0 0
e 1 0 0
f 0 0 1
g 1 1 0
h 0 1 1
i 1 1 1
j 1 1 1
k 1 0 1
l 1 0 1
m 1 0 0
n 1 0 0
o 0 0 1
p 0 0 1
q 1 0 0
r 0 1 0
s 0 1 0
t 0 1 0
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const leftMargin = 20
const thickness = 5
const wideness = 600
let size = (d) => d.elements.length*12
let setBoxes = Stack({width: thickness, padding: 6, data: sets, size})
let subsetBoxes = Stack({width: thickness, padding: 6, data: subsets, size})
let setBoxesIndex = {}
setBoxes.boxes.forEach(box => setBoxesIndex[box.d.label] = box)
let setToSubsets = {}
sets.forEach(set => setToSubsets[set.label] = [])
subsets.forEach(subset => subset.sets.forEach(set => setToSubsets[set].push(subset)))
let setStacks = {}
sets.forEach(set => {
let stack = Stack({width: thickness/2, padding:0, data: setToSubsets[set.label], size})
setStacks[set.label] = {}
stack.boxes.forEach(box => setStacks[set.label][box.d.label] = box)
})
return svg`<svg width="${width}" height="${Math.max(setBoxes.height, subsetBoxes.height)}">
${
setBoxes.boxes.map(box => `<rect x="${leftMargin}" y="${box.begin}" width="${box.width}" height="${box.height}" fill="${setColor(box.d.label)}"/><text y="${box.begin+box.height/2}">${box.d.label}</text>`)
}
${
subsetBoxes.boxes.map(box => `<rect x="${leftMargin + wideness}" y="${box.begin}" width="${box.width}" height="${box.height}"/>`)
}
${
subsetBoxes.boxes.map(box => box.d.sets.map(set => `<path d="${Band({source: [thickness/2, setBoxesIndex[set].begin + setStacks[set][box.d.label].begin], target: [wideness, box.begin], width: box.height})}" transform="translate(${leftMargin},0)" fill="${setColor(set)}" opacity="0.5" style="mix-blend-mode: multiply;"/>` ))
}
</svg>`
}
Insert cell
setColor = d3.scaleOrdinal(d3.schemeDark2)
Insert cell
Stack = ({width, padding, data, size} = {}) => {
let boxes = []
let h = 0
data.forEach( d => {
let boxH = size(d)
boxes.push({begin: h, end: h+boxH, width: width, height: boxH, d: d})
h += boxH + padding
})
return {
data,
boxes,
width,
height: h - padding
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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