Source
119 chart lines · 2 files · 3.3 kBBenchmark harness excluded · shared/mount.ts
The Simpsons episode ratings600 records · CSV · 119.7 kB
@charts-poc/demo-data/simpsonsSelection: Complete published snapshot
- id
- number
- title
- string
- original_air_date
- Date
- production_code
- string
- season
- number
- number_in_season
- number
- number_in_series
- number
- us_viewers_in_millions
- number | null
- views
- number | null
- imdb_rating
- number | null
- imdb_votes
- number | null
- image_url
- string | null
- video_url
- string | null
IMDb / Todd W. Schneiderobservablehq/plot@356f579b1d94 · revision 356f579b1d94 · test/data/simpsons.csv · Observable Plot repository MIT; upstream source credited · SHA-256 7cc6ecdcb706Pinned snapshot
cases/62-ridgeline-density/tanstack.ts62 lines · entry
cases/62-ridgeline-density/tanstack.ts
import { simpsons } from '@charts-poc/demo-data/simpsons'
import { areaY, d3Curve, defineChart, lineY, ruleY } from '@tanstack/charts'
import { scaleLinear } from 'd3-scale'
import { curveBasis } from 'd3-shape'
import { isRatedEpisode, ridgeDensity, ridgeSeasons } from './transform'
import { tanstackMount } from '../../shared/mount'
import type { ConformanceInput } from '../../types'
const colors = ['#2563eb', '#0d9488', '#d97706']
const definition = (input: ConformanceInput) => {
const seasons = ridgeSeasons(input.revision)
const rows = ridgeDensity(simpsons.filter(isRatedEpisode), seasons)
const curve = d3Curve(curveBasis)
return defineChart({
marks: [
ruleY([0, 1, 2], {
stroke: '#94a3b8',
strokeOpacity: 0.5,
}),
areaY(rows, {
x: 'imdb_rating',
y1: 'baseline',
y2: 'density',
color: 'season',
fillOpacity: 0.52,
curve,
}),
lineY(rows, {
x: 'imdb_rating',
y: 'density',
color: 'season',
strokeWidth: 1.5,
curve,
}),
],
x: {
scale: scaleLinear().domain([4, 10]),
grid: true,
axis: { label: 'IMDb rating' },
},
y: {
scale: scaleLinear().domain([-0.08, 2.86]),
axis: {
ticks: {
count: seasons.length,
format: (value) => {
const season = seasons[Math.round(value)]
return season === undefined ? '' : `Season ${season}`
},
},
},
},
color: {
range: colors,
},
margin: { left: 76 },
})
}
export const mount = tanstackMount(definition, 'Ridgeline density comparison')cases/62-ridgeline-density/transform.ts57 lines · support
cases/62-ridgeline-density/transform.ts
import { bin } from 'd3-array'
import type { SimpsonsRow } from '@charts-poc/demo-data/simpsons'
export type RatedEpisode = SimpsonsRow & {
readonly imdb_rating: number
}
export interface RidgePoint {
id: string
season: number
imdb_rating: number
baseline: number
density: number
}
const boundaries = [
4, 4.25, 4.5, 4.75, 5, 5.25, 5.5, 5.75, 6, 6.25, 6.5, 6.75, 7, 7.25, 7.5,
7.75, 8, 8.25, 8.5, 8.75, 9, 9.25, 9.5, 9.75, 10,
]
const createBins = bin<RatedEpisode, number>()
.value((row) => row.imdb_rating)
.domain([4, 10])
.thresholds(boundaries.slice(1, -1))
export function isRatedEpisode(row: SimpsonsRow): row is RatedEpisode {
return row.imdb_rating !== null
}
export function ridgeSeasons(revision: number): readonly number[] {
const offset = revision % 2
return [1 + offset, 10 + offset, 20 + offset]
}
export function ridgeDensity(
episodes: readonly RatedEpisode[],
seasons: readonly number[],
): readonly RidgePoint[] {
return seasons.flatMap((season, seasonIndex) => {
const buckets = createBins(
episodes.filter((episode) => episode.season === season),
)
const maximum = Math.max(...buckets.map((bucket) => bucket.length), 1)
return buckets.flatMap((bucket, index) => {
if (bucket.x0 === undefined || bucket.x1 === undefined) return []
return [
{
id: `${season}:${index}`,
season,
imdb_rating: (bucket.x0 + bucket.x1) / 2,
baseline: seasonIndex,
density: seasonIndex + (bucket.length / maximum) * 0.78,
},
]
})
})
}