Public
Edited
Mar 6, 2023
Fork of BI Project
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function transformObject(object, property, searchValue, replaceValue) {
return _.mapValues(object, function(value, key) {
if (_.isObject(value)) {
return transformObject(value, property, searchValue, replaceValue);
} else if (key === property) {
return value.replace(new RegExp(searchValue, 'g'), replaceValue);
} else {
return value;
}
});
}
Insert cell
function transformArray(array, property, searchValue, replaceValue) {
return array.map(item => {
if (_.isObject(item)) {
return transformObject(item, property, searchValue, replaceValue);
} else {
return item;
}
});
}


Insert cell
Insert cell
animeNew = transformArray(anime,'gross', '[$M]','');

Insert cell
Insert cell
Insert cell
Insert cell
colorObj = {
const colors = _.zipObject(topGenres, petalColors)
colors.Other = '#FFF2B4'
return colors
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
pathObjKeys = Object.keys(pathObj);

Insert cell
function greatestYear(years, year){
const smallerYears = years.filter(y => y < year);
return Math.max(...smallerYears);
}
Insert cell
Insert cell
function shuffleGenres(array) {
return array.map((item) => {
if (_.isObject(item)) {
return _.mapValues(item, function (value, key) {
if (_.isObject(value)) {
return shuffleGenres(value);
} else if (key === "genre") {
const genres = value.split(",");
const shuffledGenres = _.shuffle(genres);
return shuffledGenres.map(genre => genre.trim());
} else {
return value;
}
});
} else {
return item;
}
});
}
Insert cell
newAnime2 = shuffleGenres(animeNew);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const svg = html`<svg width=${width} height=${svgHeight}></svg>`;

d3.select(svg)
.selectAll("path")
.data(newAnime2)
.enter()
.append("path")
.attr("transform", (d, i) => `translate(${calculateGridPos(i)})`)
.attr("d", (d) => pathObj[greatestYear(pathObjKeys, d.year)])
.attr("fill", (d) => colorObj[d.genre[0]] || colorObj.Other)
.attr("stroke", (d) => colorObj[d.genre[0]] || colorObj.Other)
.attr("fill-opacity", 0.5)
.attr("stroke-width", 2);

return scrollSVG(svg);
}
Insert cell
flowers = {
// movie genre → `color` (color of petals)
// array of top genres: `topGenres`
// array of colors to map to: `petalColors`
const colorScale = d3
.scaleOrdinal()
.domain(topGenres)
.range(petalColors)
.unknown(colorObj.Other);

// `rated` → `path` (type of flower petal)
// array to map to: `petalPaths`
const pathScale = d3.scaleOrdinal().range(petalPaths);

// `rating` → `scale` (size of petals)
const minMaxRating = d3.extent(newAnime2, (d) => d.rating);
const sizeScale = d3.scaleLinear().domain(minMaxRating).range([0.2, 0.75]);

// `votes` → `numPetals` (number of petals)
const minMaxVotes = d3.extent(newAnime2, (d) => d.votes);
const numPetalScale = d3
.scaleQuantize()
.domain(minMaxVotes)
.range([5, 6, 7, 8, 9, 10]);

return _.map(newAnime2, (d, i) => {
return {
color: colorScale(d.genre[0]),
path: pathScale(greatestYear(pathObjKeys, d.year)),
scale: sizeScale(d.rating),
numPetals: numPetalScale(d.votes),
title: d.title,
translate: calculateGridPos(i) // util function that returns [x, y]
};
});
}
Insert cell
{
const svg = html`<svg width=${width} height=${svgHeight}></svg>`;

d3.select(svg)
.selectAll("path")
.data(flowers)
.enter()
.append("path")
.attr(
"transform",
(d,i) => `translate(${d.translate})scale(${d.scale || 1})`
)
.attr("d", (d) => d.path)
.attr("fill", (d) => d.color)
.attr("fill-opacity", 0.75)
.attr("stroke", (d) => d.color);

return scrollSVG(svg);
}
Insert cell
Insert cell
{
const svg = html`<svg width=${width} height=${svgHeight}></svg>`;

const g = d3
.select(svg)
.selectAll("g")
.data(flowers)
.enter()
.append("g")
.attr("transform", (d) => `translate(${d.translate})`);

g.selectAll("path")
.data((d) => {
return _.times(d.numPetals, (i) =>
Object.assign({}, d, { rotate: i * (360 / d.numPetals) })
);
})
.enter()
.append("path")
.attr("transform", (d) => `rotate(${d.rotate})scale(${d.scale})`)
.attr("d", (d) => d.path)
.attr("fill", (d) => d.color)
.attr("stroke", (d) => d.color)
.attr("fill-opacity", 0.5)
.attr("stroke-width", 3);

g.append("text")
.text((d) => _.truncate(d.title, 18))
.style("font-size", ".57em")
.style("font-style", "italic")
.attr("text-anchor", "middle")
.attr("dy", ".35em");

return scrollSVG(svg);
}
Insert cell
Insert cell
Insert cell
filtered = _.filter(newAnime2, d => {
// either the genre is in the filtered genres
return (_.includes(filteredGenres, d.genre[0]) ||
// OR the movie's genre isn't one of the top genres, and "Other" is toggled
(_.includes(filteredGenres, 'Other') && !_.includes(topGenres, d.genre[0]))) &&
// AND movie's pg rating is in filtered pg
_.includes(filteredPG, d.rated)
})
Insert cell
Insert cell
Insert cell
petalPath = "M0,0 C50,40 50,70 20,100 L0,85 L-20,100 C-50,70 -50,40 0,0"
Insert cell
petalPaths = [
'M0 0 C50 50 50 100 0 100 C-50 100 -50 50 0 0',
'M-35 0 C-25 25 25 25 35 0 C50 25 25 75 0 100 C-25 75 -50 25 -35 0',
window.localStorage.petalPath || '"M0,0 C50,40 50,70 20,100 L0,85 L-20,100 C-50,70 -50,40 0,0"',
'M0 0 C50 25 50 75 0 100 C-50 75 -50 25 0 0',
]
Insert cell
d3 = require('d3')
Insert cell
_ = require('lodash')
Insert cell
import {Inputs} from "@jashkenas/inputs"
Insert cell
import {checkbox} from "@jashkenas/inputs"
Insert cell
import {form} from '@mbostock/form-input'
Insert cell
import {calculateData} from '2683357905679f61'
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