File size: 2,642 Bytes
b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b b54f543 a9e6b9b 260c1a3 a9e6b9b b54f543 a9e6b9b b54f543 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
import { useRef, useEffect } from 'react'
import * as Plot from '@observablehq/plot'
const SpeakerPlot = ({ data }) => {
const containerRef = useRef()
const allSpeakers = data.language_table.reduce(
(sum, curr) => sum + curr.speakers,
0
)
const languages = data.language_table
.sort((a, b) => b.speakers - a.speakers)
.slice(0, 100)
.reduce((acc, d) => {
acc.push({
...d,
rank: acc.length + 1,
cumSpeakers:
acc.reduce((sum, curr) => sum + curr.speakers, 0) + d.speakers,
cumSpeakersPercent:
(acc.reduce((sum, curr) => sum + curr.speakers, 0) + d.speakers) /
allSpeakers
})
return acc
}, [])
useEffect(() => {
const plot = Plot.plot({
width: 750,
height: 500,
subtitle: 'Number of languages vs speakers covered',
x: {
label: 'Languages',
ticks: []
},
y: {
label: 'Number of Speakers (millions)'
},
color: {
legend: true,
domain: ['Speakers', 'Cumulative Speakers'],
range: ['green', 'lightgrey']
},
marks: [
Plot.barY(languages, {
x: 'rank',
y: d => d.cumSpeakers / 1e6,
fill: d => 'Cumulative Speakers',
sort: { x: 'y' },
title: d =>
`The ${
d.rank
} most spoken languages cover\n${d.cumSpeakersPercent.toLocaleString(
'en-US',
{ style: 'percent' }
)} of all speakers`,
tip: true // {y: d => d.cumSpeakers / 1e6 * 2}
}),
Plot.barY(languages, {
x: 'rank',
y: d => d.speakers / 1e6,
title: d =>
`${d.language_name}\n(${d.speakers.toLocaleString('en-US', {
notation: 'compact',
compactDisplay: 'long'
})} speakers)`,
tip: true,
fill: d => 'Speakers',
sort: { x: '-y' }
}),
Plot.crosshairX(languages, {
x: 'rank',
y: d => d.cumSpeakers / 1e6,
textStrokeOpacity: 0,
textFillOpacity: 0
}),
Plot.tip(['The 40 most spoken languages cover 80% of all speakers.'], {
x: 40,
y: languages[39].cumSpeakers / 1e6
})
]
})
containerRef.current.append(plot)
return () => plot.remove()
}, [])
return (
<div
ref={containerRef}
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
/>
)
}
export default SpeakerPlot
|