stats §8: Curaçao from ILOSTAT (SDMX), OWID, UN SDG 531, UN Comtrade 531 (cwintl + weekly timer), EU trade with CW (Eurostat ext_lt_maineu); CBS Curaçao LFS file pick fix; Curaçao detail panels on /stats/countries/CUW
All checks were successful
Deploy production / deploy (push) Successful in 1m10s
All checks were successful
Deploy production / deploy (push) Successful in 1m10s
This commit is contained in:
64
src/lib/stats/curacao.ts
Normal file
64
src/lib/stats/curacao.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
// §8 Curaçao detail series (CBS Curaçao, Eurostat, ILOSTAT, OWID, UN SDG, UN Comtrade), all with
|
||||
// region CUW in stats.series. Loaded by /stats/countries/CUW next to the World Bank profile.
|
||||
|
||||
/** CBS Curaçao GDP by industry (ISIC 4 sections as published, mln ANG) with short labels. */
|
||||
export const CW_INDUSTRIES: Record<string, string> = {
|
||||
'a+b': 'Agriculture & mining',
|
||||
c: 'Manufacturing',
|
||||
'd+e': 'Utilities',
|
||||
f: 'Construction',
|
||||
g: 'Trade',
|
||||
h: 'Transport',
|
||||
i: 'Hotels & restaurants',
|
||||
j: 'ICT',
|
||||
k: 'Finance',
|
||||
l: 'Real estate',
|
||||
m: 'Professional services',
|
||||
n: 'Admin services',
|
||||
o: 'Public administration',
|
||||
p: 'Education',
|
||||
q: 'Health',
|
||||
r: 'Arts & recreation',
|
||||
's+t': 'Other services'
|
||||
};
|
||||
|
||||
export const CW_NIGHT_MARKETS: Record<string, string> = {
|
||||
europe: 'Europe',
|
||||
north_america: 'North America',
|
||||
south_america: 'South America',
|
||||
caribbean: 'Caribbean',
|
||||
others: 'Other'
|
||||
};
|
||||
|
||||
export const EU_TRADE = (indic: string) => `eurostat:ext_lt_maineu:${indic}.TOTAL.CW.EU27_2020`;
|
||||
|
||||
export const CW_SERIES = [
|
||||
'cw:cpi:index',
|
||||
'cw:cpi:yoy',
|
||||
'cw:gdp:gdp',
|
||||
'cw:gdp:real_growth_pct',
|
||||
...Object.keys(CW_INDUSTRIES).map((k) => `cw:gdp:${k}`),
|
||||
'cw:gov:r.total',
|
||||
'cw:gov:e.total',
|
||||
'cw:gov:balance',
|
||||
'cw:pop:jan1',
|
||||
'cw:pop:census',
|
||||
...['total', 'm', 'f', '15-24'].map((g) => `cw:lfs:unemployment_rate_pct:${g}`),
|
||||
'cw:lfs:net_participation_pct:total',
|
||||
'cw:tour:cruise_pax',
|
||||
'cw:tour:daytrippers',
|
||||
'cw:tour:nights',
|
||||
...Object.keys(CW_NIGHT_MARKETS).map((m) => `cw:tour:nights:${m}`),
|
||||
EU_TRADE('MIO_EXP_VAL'),
|
||||
EU_TRADE('MIO_IMP_VAL'),
|
||||
EU_TRADE('MIO_BAL_VAL'),
|
||||
'ilostat:une_deap_sex_age_rt:total:15plus',
|
||||
'owid:cw:population',
|
||||
'owid:cw:co-emissions-per-capita',
|
||||
'owid:cw:median-age',
|
||||
'unsdg:eg_fec_rnew',
|
||||
'comtrade:cw:imports:world',
|
||||
'comtrade:cw:exports:world',
|
||||
'comtrade:cw:imports:usa',
|
||||
'comtrade:cw:imports:nld'
|
||||
];
|
||||
@@ -1,6 +1,7 @@
|
||||
import { error, redirect } from '@sveltejs/kit';
|
||||
import { cached, loadSeries } from '#lib/server/stats.js';
|
||||
import { isCountryPage, PROFILE_SERIES } from '#lib/stats/countries.js';
|
||||
import { CW_SERIES } from '#lib/stats/curacao.js';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ params, url }) => {
|
||||
@@ -16,7 +17,9 @@ export const load: PageServerLoad = async ({ params, url }) => {
|
||||
`wb:NY.GDP.PCAP.PP.KD:${c}`,
|
||||
`wb:SP.DYN.LE00.IN:${c}`,
|
||||
`wb:FP.CPI.TOTL.ZG:${c}`
|
||||
])
|
||||
]),
|
||||
// §8: Curaçao detail from CBS Curaçao and the international APIs (ids carry no code suffix).
|
||||
...(code === 'CUW' ? CW_SERIES : [])
|
||||
])
|
||||
);
|
||||
return { code, series };
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import StatChart from '#lib/stats/StatChart.svelte';
|
||||
import Kpi from '#lib/stats/Kpi.svelte';
|
||||
import { change, latest, lineOption, type Line, type StatPoint } from '#lib/stats/chart.js';
|
||||
import {
|
||||
barRankOption,
|
||||
change,
|
||||
latest,
|
||||
lineOption,
|
||||
type Line,
|
||||
type StatPoint
|
||||
} from '#lib/stats/chart.js';
|
||||
import { CW_INDUSTRIES, CW_NIGHT_MARKETS, EU_TRADE } from '#lib/stats/curacao.js';
|
||||
import { compact, num, period } from '#lib/stats/format.js';
|
||||
import { COUNTRY } from '#lib/stats/regions.js';
|
||||
import { COUNTRY_COLOR, FLAG } from '#lib/stats/countries.js';
|
||||
@@ -54,6 +62,23 @@
|
||||
const kDebt = $derived(lastOf(pick('imf:GGXWDG_NGDP', 'wb:GC.DOD.TOTL.GD.ZS')));
|
||||
const popDelta = $derived(change(pts('wb:SP.POP.TOTL'), 10)?.pct ?? null);
|
||||
const imfCovered = $derived(has('imf:NGDP_RPCH'));
|
||||
|
||||
// §8 Curaçao detail series: stored without the `:CUW` suffix.
|
||||
const cw = (id: string): StatPoint[] => s[id]?.points ?? [];
|
||||
const isCw = $derived(c === 'CUW' && cw('cw:cpi:index').length > 0);
|
||||
const cwGdpYear = $derived(latest(cw('cw:gdp:gdp'))?.[0]);
|
||||
const cwIndustries = $derived(
|
||||
Object.entries(CW_INDUSTRIES)
|
||||
.map(([k, label]) => ({
|
||||
label,
|
||||
value: cw(`cw:gdp:${k}`).find(([d]) => d === cwGdpYear)?.[1] ?? NaN
|
||||
}))
|
||||
.filter((r) => Number.isFinite(r.value))
|
||||
);
|
||||
const cwCpi = $derived(latest(cw('cw:cpi:yoy')));
|
||||
const cwPop = $derived(latest(cw('cw:pop:jan1')));
|
||||
const cwUnemp = $derived(latest(cw('cw:lfs:unemployment_rate_pct:total')));
|
||||
const cwGrowth = $derived(latest(cw('cw:gdp:real_growth_pct')));
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -73,9 +98,11 @@
|
||||
<p>
|
||||
{#if c === 'CUW'}
|
||||
Curaçao has been a country within the Kingdom of the Netherlands since 2010, with about
|
||||
150,000 inhabitants. The IMF's World Economic Outlook doesn't cover it, so the headline
|
||||
numbers here come from the World Bank; detailed CBS Curaçao and central bank series are on
|
||||
their way.
|
||||
158,000 inhabitants. The IMF's World Economic Outlook doesn't cover it, so the headline
|
||||
numbers come from the World Bank; the detail further down comes from CBS Curaçao (the island's
|
||||
statistics office), Eurostat, ILOSTAT, Our World in Data and the UN. Amounts in guilders (ANG,
|
||||
pegged at 1.79 to the US dollar). The central bank's balance-of-payments tables can't be
|
||||
fetched automatically, so they aren't here yet.
|
||||
{:else}
|
||||
{name} at a glance, from the World Bank's development indicators and the IMF World Economic Outlook{imfCovered
|
||||
? ' (dashed lines are IMF forecasts)'
|
||||
@@ -365,33 +392,35 @@
|
||||
|
||||
<h2 class="stats-section-title">Government and energy</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Government finances"
|
||||
subtitle={has('imf:GGXWDG_NGDP')
|
||||
? '% of GDP · IMF (general government)'
|
||||
: '% of GDP · World Bank (central government)'}
|
||||
sources={has('imf:GGXWDG_NGDP') ? ['imf'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
has('imf:GGXWDG_NGDP')
|
||||
? [
|
||||
...imfLines('imf:GGXWDG_NGDP', 'Debt', '#e11d48'),
|
||||
...imfLines('imf:GGR_G01_GDP_PT', 'Revenue', '#10b981'),
|
||||
...imfLines('imf:G_X_G01_GDP_PT', 'Spending', '#3b82f6')
|
||||
]
|
||||
: [
|
||||
{ name: 'Debt', points: pts('wb:GC.DOD.TOTL.GD.ZS'), color: '#e11d48' },
|
||||
{ name: 'Revenue', points: pts('wb:GC.REV.XGRT.GD.ZS'), color: '#10b981' },
|
||||
{ name: 'Expense', points: pts('wb:GC.XPN.TOTL.GD.ZS'), color: '#3b82f6' }
|
||||
],
|
||||
{ unit: '% GDP', decimals: 1 }
|
||||
)}
|
||||
note={!has('imf:GGXWDG_NGDP') && !has('wb:GC.DOD.TOTL.GD.ZS')
|
||||
? 'No government finance data for this country yet.'
|
||||
: ''}
|
||||
/>
|
||||
{#if !isCw || has('imf:GGXWDG_NGDP') || has('wb:GC.DOD.TOTL.GD.ZS')}
|
||||
<StatChart
|
||||
title="Government finances"
|
||||
subtitle={has('imf:GGXWDG_NGDP')
|
||||
? '% of GDP · IMF (general government)'
|
||||
: '% of GDP · World Bank (central government)'}
|
||||
sources={has('imf:GGXWDG_NGDP') ? ['imf'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
has('imf:GGXWDG_NGDP')
|
||||
? [
|
||||
...imfLines('imf:GGXWDG_NGDP', 'Debt', '#e11d48'),
|
||||
...imfLines('imf:GGR_G01_GDP_PT', 'Revenue', '#10b981'),
|
||||
...imfLines('imf:G_X_G01_GDP_PT', 'Spending', '#3b82f6')
|
||||
]
|
||||
: [
|
||||
{ name: 'Debt', points: pts('wb:GC.DOD.TOTL.GD.ZS'), color: '#e11d48' },
|
||||
{ name: 'Revenue', points: pts('wb:GC.REV.XGRT.GD.ZS'), color: '#10b981' },
|
||||
{ name: 'Expense', points: pts('wb:GC.XPN.TOTL.GD.ZS'), color: '#3b82f6' }
|
||||
],
|
||||
{ unit: '% GDP', decimals: 1 }
|
||||
)}
|
||||
note={!has('imf:GGXWDG_NGDP') && !has('wb:GC.DOD.TOTL.GD.ZS')
|
||||
? 'No government finance data for this country yet.'
|
||||
: ''}
|
||||
/>
|
||||
{/if}
|
||||
<StatChart
|
||||
title="Energy"
|
||||
subtitle="net energy imports (% of use) · renewable share of electricity"
|
||||
@@ -409,6 +438,281 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isCw}
|
||||
<h2 class="stats-section-title">Curaçao in detail</h2>
|
||||
<div class="kpis">
|
||||
<Kpi
|
||||
label="Population, 1 Jan"
|
||||
value={compact(cwPop?.[1])}
|
||||
sub={`CBS Curaçao · ${period(cwPop?.[0], 'A')}`}
|
||||
{color}
|
||||
/>
|
||||
<Kpi
|
||||
label="Inflation"
|
||||
value={num(cwCpi?.[1], 1)}
|
||||
unit="%"
|
||||
sub={`year on year · ${period(cwCpi?.[0], 'M')}`}
|
||||
color="#e11d48"
|
||||
/>
|
||||
<Kpi
|
||||
label="Real growth"
|
||||
value={num(cwGrowth?.[1], 1)}
|
||||
unit="%"
|
||||
sub={period(cwGrowth?.[0], 'A')}
|
||||
color="#3b82f6"
|
||||
/>
|
||||
<Kpi
|
||||
label="Unemployment"
|
||||
value={num(cwUnemp?.[1], 1)}
|
||||
unit="%"
|
||||
sub={`labour force survey · ${period(cwUnemp?.[0], 'A')}`}
|
||||
color="#a855f7"
|
||||
/>
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Consumer prices since 1970"
|
||||
subtitle="CPI (2023 = 100) · inflation year on year (%) on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'CPI', points: cw('cw:cpi:index'), color: '#64748b', kind: 'area' },
|
||||
{ name: 'Inflation', points: cw('cw:cpi:yoy'), color: '#e11d48', right: true }
|
||||
],
|
||||
{ unit: 'index', rightUnit: '%', decimals: 1, zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="GDP"
|
||||
subtitle="nominal, million guilders · real growth (%) on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'GDP', points: cw('cw:gdp:gdp'), color, kind: 'bar' },
|
||||
{
|
||||
name: 'Real growth',
|
||||
points: cw('cw:gdp:real_growth_pct'),
|
||||
color: '#3b82f6',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ unit: 'mln ANG', rightUnit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="GDP by industry"
|
||||
subtitle={`gross value added, million guilders · ${period(cwGdpYear, 'A')}`}
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
height="420px"
|
||||
option={(t) => barRankOption(t, cwIndustries, { decimals: 0, unit: 'mln ANG', color })}
|
||||
/>
|
||||
<StatChart
|
||||
title="Population since 1900"
|
||||
subtitle="1 January (31 December before 1992) and census counts · UN estimate dashed"
|
||||
sources={['cbscw', 'owid']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Population', points: cw('cw:pop:jan1'), color, kind: 'area' },
|
||||
{ name: 'Census', points: cw('cw:pop:census'), color: '#0f172a', kind: 'bar' },
|
||||
{
|
||||
name: 'UN WPP (via OWID)',
|
||||
points: cw('owid:cw:population'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ decimals: 0, unit: 'people' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Unemployment"
|
||||
subtitle="% of the labour force · CBS labour force survey (no survey in 2021 and 2023), ILO dashed"
|
||||
sources={['cbscw', 'ilostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Total', points: cw('cw:lfs:unemployment_rate_pct:total'), color: '#a855f7' },
|
||||
{ name: 'Men', points: cw('cw:lfs:unemployment_rate_pct:m'), color: '#3b82f6' },
|
||||
{ name: 'Women', points: cw('cw:lfs:unemployment_rate_pct:f'), color: '#ec4899' },
|
||||
{
|
||||
name: 'Aged 15–24',
|
||||
points: cw('cw:lfs:unemployment_rate_pct:15-24'),
|
||||
color: '#f97316'
|
||||
},
|
||||
{
|
||||
name: 'ILO estimate (15+)',
|
||||
points: cw('ilostat:une_deap_sex_age_rt:total:15plus'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ unit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Tourism"
|
||||
subtitle="cruise passengers and daytrippers · stay-over nights on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Cruise passengers',
|
||||
points: cw('cw:tour:cruise_pax'),
|
||||
color: '#06b6d4',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Daytrippers',
|
||||
points: cw('cw:tour:daytrippers'),
|
||||
color: '#eab308',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Stay-over nights',
|
||||
points: cw('cw:tour:nights'),
|
||||
color: '#e11d48',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ decimals: 0, rightUnit: 'nights' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Stay-over nights by market"
|
||||
subtitle="tourist nights by region of residence"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
Object.entries(CW_NIGHT_MARKETS).map(([k, label], i) => ({
|
||||
name: label,
|
||||
points: cw(`cw:tour:nights:${k}`),
|
||||
color: ['#3b82f6', '#e11d48', '#10b981', '#eab308', '#94a3b8'][i],
|
||||
kind: 'bar' as const,
|
||||
stack: 'nights'
|
||||
})),
|
||||
{ decimals: 0, unit: 'nights' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Government revenue and expenditure"
|
||||
subtitle="million guilders · balance as bars (recent years provisional)"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Revenue', points: cw('cw:gov:r.total'), color: '#10b981' },
|
||||
{ name: 'Expenditure', points: cw('cw:gov:e.total'), color: '#3b82f6' },
|
||||
{ name: 'Balance', points: cw('cw:gov:balance'), color: '#e11d48', kind: 'bar' }
|
||||
],
|
||||
{ unit: 'mln ANG', decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Trade with the EU"
|
||||
subtitle="EU27 goods exports to and imports from Curaçao, million €"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'EU exports to Curaçao',
|
||||
points: cw(EU_TRADE('MIO_EXP_VAL')),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{
|
||||
name: 'EU imports from Curaçao',
|
||||
points: cw(EU_TRADE('MIO_IMP_VAL')),
|
||||
color: '#f97316'
|
||||
},
|
||||
{
|
||||
name: 'EU balance',
|
||||
points: cw(EU_TRADE('MIO_BAL_VAL')),
|
||||
color: '#94a3b8',
|
||||
kind: 'bar'
|
||||
}
|
||||
],
|
||||
{ unit: 'mln €', decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Goods trade (as reported by Curaçao)"
|
||||
subtitle="US$ · only 2017–2020 are reported to the UN"
|
||||
sources={['comtrade']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Imports',
|
||||
points: cw('comtrade:cw:imports:world'),
|
||||
color: '#e11d48',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Exports',
|
||||
points: cw('comtrade:cw:exports:world'),
|
||||
color: '#10b981',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Imports from the US',
|
||||
points: cw('comtrade:cw:imports:usa'),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{ name: 'Imports from NL', points: cw('comtrade:cw:imports:nld'), color: '#f97316' }
|
||||
],
|
||||
{ decimals: 0, unit: 'US$' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Climate and energy"
|
||||
subtitle="CO₂ per person (t) · renewable share of final energy (%) on the right"
|
||||
sources={['owid', 'unsdg']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'CO₂ per person',
|
||||
points: cw('owid:cw:co-emissions-per-capita'),
|
||||
color: '#64748b'
|
||||
},
|
||||
{
|
||||
name: 'Renewable share',
|
||||
points: cw('unsdg:eg_fec_rnew'),
|
||||
color: '#10b981',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ unit: 't', rightUnit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.back {
|
||||
display: inline-flex;
|
||||
|
||||
Reference in New Issue
Block a user