File size: 3,151 Bytes
867080c b4a0c57 7cdde63 92d8154 7cdde63 3680a5f 92d8154 7cdde63 3680a5f 71ab1e9 3680a5f 7cdde63 71ab1e9 92b2164 7c06aef 867080c 00e463a b4a0c57 00e463a 867080c 00e463a 867080c b4a0c57 867080c 92d8154 7c06aef 867080c 7c06aef 941d5c5 867080c 92d8154 00e463a 867080c 00e463a abd65a6 00e463a abd65a6 7cdde63 00e463a 867080c e8341d2 867080c 7cdde63 92d8154 7cdde63 867080c b4a0c57 867080c |
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 102 103 104 105 106 107 108 |
import { useRef, useEffect, useState } from 'react'
import * as Plot from '@observablehq/plot'
const smoothProgressBar = fraction => {
const blocks = ['β', 'β', 'β', 'β', 'β', 'β', 'β', 'β']
const width = 10
const totalUnits = width * 8
const filledUnits = Math.round(fraction * totalUnits)
const fullBlocks = Math.floor(filledUnits / 8)
const remainder = filledUnits % 8
return (
'β'.repeat(fullBlocks) + (remainder > 0 ? blocks[remainder - 1] : '') || 'β'
)
}
const makeTitle = data => d => {
const cData = data[d.properties?.ISO_A2_EH]
const languages = cData?.languages.toSorted(
(a, b) => b.population - a.population
)
const pop = languages?.map(a => a.population).reduce((prev, a) => prev + a, 0)
const langstring =
languages
?.slice(0, 10)
.map(
a =>
`${smoothProgressBar(a.population / pop)} ${
a.name
} β ${a.score === null || a.score === undefined ? "n/a" : a.score.toFixed(2)}`
)
.join('\n\n') + (languages?.length > 10 ? `\n\n...` : '')
return `${d.properties.ADMIN} β ${cData?.score === null || cData?.score === undefined ? "n/a" : cData.score.toFixed(2)}\n\n${langstring}`
}
const WorldMap = ({ data, width = 750, height = 500, allLanguages = [] }) => {
const containerRef = useRef()
const [mapData, setMapData] = useState()
useEffect(() => {
fetch('/world.geo.json')
.then(res => res.json())
.then(setMapData)
}, [])
useEffect(() => {
if (mapData === undefined || data === undefined) return
const countriesDict = data.reduce((acc, country) => {
acc[country.iso2] = country
return acc
}, {})
// Count languages that have any evaluation data
const evaluatedLanguagesCount = allLanguages.filter(lang => {
const hasAnyScores = [
'translation_from_bleu',
'translation_to_bleu',
'classification_accuracy',
'mmlu_accuracy',
'arc_accuracy',
'truthfulqa_accuracy',
'mgsm_accuracy'
].some(metric => lang[metric] !== null && lang[metric] !== undefined)
return hasAnyScores
}).length
const plot = Plot.plot({
subtitle: `Language Proficiency Score by Country (Coverage: ~${evaluatedLanguagesCount} languages evaluated)`,
width: width,
height: height,
projection: 'equal-earth',
marks: [
Plot.geo(mapData, {
fill: d => countriesDict[d.properties?.ISO_A2_EH]?.score,
title: makeTitle(countriesDict),
tip: true
})
],
color: {
scheme: 'RdYlGn',
unknown: '#d0d0d0',
label: 'Score',
legend: true,
domain: [0, 1],
pivot: 0.5
},
style: {
fontFamily: 'monospace'
}
})
containerRef.current.append(plot)
return () => plot.remove()
}, [mapData, data, width, height])
return (
<div
ref={containerRef}
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
/>
)
}
export default WorldMap
|