Public
Edited
Jan 24, 2023
1 star
Insert cell
md`# Pokemon Types

Every pokemon has one or two *types* -- elemental affinities that determine the mon's strengths and weaknesses. What makes Pokemon interesting is when these types combine, creating tons of combinations. This notebook asks some questions such as:

* what are the most common typings?
* what type combinations are unused?
* which evolution families have unique typings?
`
Insert cell
md`## Type Incidence Graph`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vl.markLine()
.data(genTypeData.slice(1))
.encode(
vl.x().field('gen'),
vl.y().fieldQ('count')
)
.render()
Insert cell
genTypeData = {
const byGens = _.groupBy(pokedexList, (mon) => mon.gen);
const genCombos = []
for (const i of _.range(1, 10)) {
const mons = byGens[i]
genCombos[i] = i > 1 ? new Set(genCombos[i-1]) : new Set()
for (const mon of mons) {
genCombos[i].add(getTypeString(mon.types))
}
}
return genCombos.map((item, i) => ({ gen: i, count: item.size}));
}
Insert cell
function getTypeString(combo) {
return _.sortBy(combo, type => types.indexOf(type)).join('-')
}
Insert cell
// Types only used by legendary-ish pokemon
{
const result = [];
for (const typeCombo of allPossibleTypeCombos) {
const mons = pokedexList.filter((mon) => typeEquals(mon.types, typeCombo));
if (!mons.length) continue;
if (mons.every((mon) => isSubLegendary(mon))) {
result.push(typeCombo);
}
}
return result;
}
Insert cell
// Types only used by mega evolutions
{
const result = [];
for (const typeCombo of allPossibleTypeCombos) {
const mons = pokedexList.filter((mon) => typeEquals(mon.types, typeCombo));
if (!mons.length) continue;
if (mons.every((mon) => isMega(mon))) {
result.push(typeCombo);
}
}
return result;
}
Insert cell
types.filter(type => !_.uniq(unusedTypes.flat()).includes(type))
Insert cell
md`## Unused Type Combinations

There are ${unusedTypes.length} unused type combinations. The following type combinations are possible but are not used by any Pokemon.

${unusedTypes.map(combo => `* ${combo.join(', ')}`).join('\n')}`
Insert cell
unusedTypes = allPossibleTypeCombos.filter(combo => !usedTypes.some(used => typeEquals(used, combo)))
Insert cell
function typeEquals(combo1, combo2) {
return _.isEqual(_.sortBy(combo1), _.sortBy(combo2))
}
Insert cell
allPossibleTypeCombos = {
const list = []
for (let i = 0; i < types.length; i++) {
list.push([types[i]])
for (let j = i+1; j < types.length; j++) {
list.push([types[i], types[j]])
}
}
return list
}
Insert cell
Insert cell
Insert cell
monsByTypeCombo = _.groupBy(distinctTypePokedex, (mon) =>
getTypeString(mon.types)
)
Insert cell
distinctTypePokedex = pokedexList.filter((mon) => !isSameTypeForme(mon))
Insert cell
usedTypes = _(pokedexList).map(mon => [...mon.types].sort()).uniqWith(_.isEqual).value()
Insert cell
typesToIndex = _.mapValues(_.invert(types), val => parseInt(val))
Insert cell
import {
pokedexList,
getSpriteUrl,
isSameTypeForme,
types,
typeColors,
isMega,
isSubLegendary,
isLegendary,
isMythical,
isParadox,
isUltraBeast,
isRegionalForme,
isFossil
} from "@tesseralis/pokemon-dataviz"
Insert cell
d3 = require("d3@5")
Insert cell
_ = require("lodash@4")
Insert cell
import { vl } from '@vega/vega-lite-api-v5'
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