Public
Edited
Apr 22, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Music tracking data - Genre Wordcloud.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
musicData = musicTrackingDataGenreWordcloud.map((d) => ({
genre: d["genre"],
songsinLibrary: d["songsInLibrary"],
playedSongs: d["playedSongs"],
timePlayed: d["timePlayed"],
sharePercent: d["sharePercent"]
}))
Insert cell
Insert cell
minDuration = d3.min(musicData, (d) => d.songsinLibrary)
Insert cell
maxDuration = d3.max(musicData, (d) => d.songsinLibrary)
Insert cell
minSinceLastPlayed = d3.min(musicData, (d) => d.playedSongs)
Insert cell
maxSinceLastPlayed = d3.max(musicData, (d) => d.playedSongs)
Insert cell
minPlayDuration = d3.min(musicData, (d) => d.timePlayed)
Insert cell
maxPlayDuration = d3.max(musicData, (d) => d.timePlayed)
Insert cell
durationCal = {
const newData = [];
for (let i = 0; i < musicData.length; i++) {
newData.push([
musicData[i].songsinLibrary / maxDuration,
musicData[i].playedSongs / maxSinceLastPlayed < 0
? 0
: musicData[i].playedSongs / maxSinceLastPlayed,
musicData[i].songsinLibrary / maxDuration
]);
}
return newData;
}
Insert cell
meta = durationCal
Insert cell
viewof N = html`<input type=range min=200 max=83142 step=1 value=100>`
Insert cell
viewof perplexity = html`<input type=range min=0 max=500 step=1 value=10>`
Insert cell
Insert cell
Insert cell
Insert cell
draw = {
context.fillStyle = "rgba(255,255,255,0.4)"; // a cheap blur effect
context.fillRect(0, 0, width, height);
const X = d3
.scaleLinear()
.domain(d3.extent(solution, (d) => d[dimX]))
.range([20, width - 20]);
const Y = d3
.scaleLinear()
.domain(d3.extent(solution, (d) => d[dimY]))
.range([20, (width * 2) / 3 - 20]);
const radius = 150 / Math.sqrt(10 + solution.length);
solution.forEach((point, i) => {
let k = meta[i];
context.beginPath();
context.arc(X(point[dimX]), Y(point[dimY]), radius, 0, 2 * Math.PI);
context.fillStyle = d3.hsl(k[0] * 360, 0.3 + 0.5 * k[1], 0.3 + 0.5 * k[2]);
// (`rgb(${k[0]*256 | 0}, ${k[1]*256 | 0}, ${k[2]*256 | 0})`);
context.fill();
});
return md`A simple loop: we draw a circle for each of the points, its color informed by the points array, its position informed by the solution array.`;
}
Insert cell
// genre = ["r&b", "techno", "techno", "rock"]
Insert cell
// music = d3.range(1000).map((d) => ({
// id: d,
// duration: Math.random() * 180 + 30,
// genre: randomChoice(genre)
// }))
Insert cell
// randomChoice = (arr) => {
// return arr[Math.floor(Math.random() * arr.length)];
// }
Insert cell
// one could probably use the more accurate model of color distances given in
// https://beta.observablehq.com/@mbostock/measuring-color-difference
function distanceHSL(a, b) {
let d = 0,
s = 0;
let i = 0;
s = Math.sin(Math.PI * (a[i] - b[i]));
d += s * s;
i = 1;
s = a[i] - b[i];
d += (s * s) / 2;
i = 2;
s = a[i] - b[i];
d += (s * s) / 2;
return Math.sqrt(d);
}
Insert cell
dists = meta.map((a) => meta.map((b) => distanceHSL(a, b)))

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3")
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