Published
Edited
Mar 8, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//
// Computes data structures for mapping category names to integer numbers
// and vice-versa
//
function categoryMaps(categorical) {
let indexToCat = {};
let catToIndex = {};
let dimensions = getDimensions(categorical);
for (let dim of dimensions) {
indexToCat[dim] = [];
catToIndex[dim] = new Map();
}
for (let row of categorical) {
for (let dim of dimensions) {
if (!catToIndex[dim].has(row[dim])) {
catToIndex[dim].set(row[dim], indexToCat[dim].length);
indexToCat[dim].push(row[dim]);
}
}
}
return { indexToCat, catToIndex };
}
Insert cell
data = titanic
Insert cell
//
// Transforms data to a tensor adding two additional dimensions which are random samples of a unit disk
//
tensor = {
return tf.tensor(
data.map(row => {
const a = Math.random() * 2 * Math.PI;
const r = Math.sqrt(Math.random());
return dimensions
.map(d => catToIndex[d].get(row[d]))
.concat([r * Math.cos(a), r * Math.sin(a)]);
})
);
}
Insert cell
catMaps = categoryMaps(data)
Insert cell
indexToCat = catMaps.indexToCat
Insert cell
catToIndex = catMaps.catToIndex
Insert cell
getDimensions = categorical => Object.keys(categorical[0])
Insert cell
dimensions = getDimensions(data)
Insert cell
colorDimensionIndex = dimensions.lastIndexOf(colorDimension)
Insert cell
textureDimensionIndex = dimensions.lastIndexOf(textureDimension)
Insert cell
Insert cell
function makePalette(scale, ncolors) {
let palette = [];
for (let i = 0; i < ncolors; i++) {
palette.push(scale((1 + i) / (ncolors + 1)));
}
return palette;
}
Insert cell
Insert cell
dimPalette = makePalette(
dimensionScales[colorDimensionIndex],
indexToCat[colorDimension].length
)
Insert cell
texturePalette = makePalette(
dimensionScales[textureDimensionIndex],
indexToCat[textureDimension].length
)
Insert cell
Insert cell
coords = {
const ts = await tf.tsne(tensor);

await ts.iterateKnn(ts.knnIterations());

const tsneIterations = 333;
for (let i = 0; i < tsneIterations; ++i) {
await ts.iterate(3);
yield ts.coordsArray();
}
}
Insert cell
Insert cell
import { data as titanic } from "@john-guerra/parallel-sets"
Insert cell
d3 = require("d3@6")
Insert cell
import { Radio } from "@observablehq/inputs"
Insert cell
import { swatches } from "@d3/color-legend"
Insert cell
import { ramp, scales, displayPalettes } from "@makio135/give-me-colors"
Insert cell
//
// Require "black magic" to import tensor flow core and the tsne tf module
// (Thanks @Fil)
//
tf = {
replay;
const r = require.alias({
"@tensorflow/tfjs-core": "@tensorflow/tfjs-core@0.14.3",
"@tensorflow/tfjs-tsne": "@tensorflow/tfjs-tsne@0.2.0"
});
const [tf, tsne] = await Promise.all([
r("@tensorflow/tfjs-core"),
r("@tensorflow/tfjs-tsne")
]);
tf.tsne = tsne.tsne;
return tf;
}
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