forskjeller.naiv.no/public/boligeierskap/app.js
Ole-Morten Duesund 4f82236b8b Ny visualisering: hvem eier egentlig boligen din? SSB-data 2015–2024
Tre diagrammer basert på SSB-tabellene 14068, 14059 og 14065:
- Kakediagram: 34 % eier fritt, 38 % eier med banklån, 28 % leier
- Stablet stolpe: gjeldsbyrde over tid (lån >3M tredoblet seg)
- Horisontal stablet: eierskap etter husholdningstype (65 % av unge leier)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:52:47 +01:00

248 lines
7.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SSB data: Boligeierskap og boligøkonomi
// Tabell 14068: Boligeierskap etter husholdningstype (prosent)
// Tabell 14059: Boligøkonomi etter eierstatus (gjeldsstørrelse)
// Tabell 14065: Boliglån og boligutgifter (gjeld vs verdi)
// Hentet 2026-03-16 via SSB PxWeb API v2
// --- Data ---
// Eierskap alle husholdninger 2024 (tabell 14068):
// Selveier 57.5%, Andelseier 14.8%, Leier 27.7%
// Total eiere = 72.3%
// Av eiere uten boliglån: 47.6% (tabell 14059, 2024)
// Eier fritt = 72.3 × 0.476 = 34.4%
// Eier med lån = 72.3 × 0.524 = 37.9%
// Gjeldsstørrelse blant eiere med lån (tabell 14059, "I alt")
const YEARS = ['2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024'];
const LOAN_DIST = {
under1M: [17.2, 15.3, 13.9, 13.5, 13.2, 12.7, 13.6, 12.4, 11.7, 12.1],
from1to2M:[17.0, 16.8, 16.2, 15.1, 14.9, 14.9, 14.2, 14.8, 14.4, 14.8],
from2to3M:[ 8.2, 9.7, 10.0, 9.7, 10.3, 10.5, 12.1, 12.1, 11.9, 11.8],
over3M: [ 4.5, 5.1, 6.2, 6.8, 8.1, 8.9, 10.9, 12.0, 12.2, 13.8]
};
// Eierskap etter husholdningstype 2024 (tabell 14068)
const HOUSEHOLD_TYPES = [
{ name: 'Aleneboende 1644', selveier: 20.7, andel: 13.8, leier: 65.5 },
{ name: 'Par uten barn 1644', selveier: 41.6, andel: 21.8, leier: 36.6 },
{ name: 'Enslige forsørgere 017', selveier: 50.1, andel: 11.6, leier: 38.3 },
{ name: 'Aleneboende 4566', selveier: 54.7, andel: 17.2, leier: 28.1 },
{ name: 'Aleneboende 67+', selveier: 60.0, andel: 23.0, leier: 17.0 },
{ name: 'Par med barn 06', selveier: 70.8, andel: 12.1, leier: 17.1 },
{ name: 'Par uten barn 67+', selveier: 78.7, andel: 15.2, leier: 6.1 },
{ name: 'Par med barn 717', selveier: 82.9, andel: 8.2, leier: 8.8 },
{ name: 'Par uten barn 4566', selveier: 82.2, andel: 11.6, leier: 6.1 },
{ name: 'Par med barn 18+', selveier: 87.7, andel: 6.8, leier: 5.6 },
];
// --- Formattering ---
function fmtPct(n) {
return n.toLocaleString('nb-NO', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + '\u202f%';
}
const GRID_COLOR = 'rgba(0,0,0,0.06)';
const TICK_COLOR = '#8a857e';
function baseOpts() {
return {
responsive: true, maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: '#1a1714',
titleColor: '#f5f2eb',
bodyColor: 'rgba(245,242,235,0.7)',
padding: 10,
cornerRadius: 4,
titleFont: { family: 'DM Sans', size: 12 },
bodyFont: { family: 'DM Sans', size: 12 }
}
},
scales: {
x: {
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, maxRotation: 0 },
grid: { display: false },
border: { color: 'rgba(0,0,0,0.1)' }
},
y: {
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, callback: v => v + ' %' },
grid: { color: GRID_COLOR },
border: { dash: [3, 3], color: 'transparent' }
}
}
};
}
// --- Diagram 1: Kakediagram (doughnut) ---
new Chart(document.getElementById('chart1'), {
type: 'doughnut',
data: {
labels: ['Eier fritt (34 %)', 'Eier med lån (38 %)', 'Leier (28 %)'],
datasets: [{
data: [34.4, 37.9, 27.7],
backgroundColor: ['#2c6e49', '#1a4a8a', '#c0392b'],
borderColor: '#fff',
borderWidth: 3,
hoverOffset: 8
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '55%',
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(c) {
return ' ' + c.label + ': ' + fmtPct(c.parsed);
}
},
backgroundColor: '#1a1714',
titleColor: '#f5f2eb',
bodyColor: 'rgba(245,242,235,0.7)',
padding: 10,
cornerRadius: 4,
titleFont: { family: 'DM Sans', size: 12 },
bodyFont: { family: 'DM Sans', size: 12 }
}
}
}
});
// --- Diagram 2: Gjeldsbyrde over tid (stablet stolpe) ---
var chart2Opts = baseOpts();
chart2Opts.scales.y.stacked = true;
chart2Opts.scales.x.stacked = true;
chart2Opts.scales.y.max = 55;
chart2Opts.plugins.tooltip = {
mode: 'index',
callbacks: {
label: function(c) {
return ' ' + c.dataset.label + ': ' + fmtPct(c.parsed.y);
}
},
backgroundColor: '#1a1714',
titleColor: '#f5f2eb',
bodyColor: 'rgba(245,242,235,0.7)',
padding: 10,
cornerRadius: 4,
titleFont: { family: 'DM Sans', size: 12 },
bodyFont: { family: 'DM Sans', size: 12 }
};
new Chart(document.getElementById('chart2'), {
type: 'bar',
data: {
labels: YEARS,
datasets: [
{
label: 'Under 1 mill',
data: LOAN_DIST.under1M,
backgroundColor: '#27ae60cc',
borderColor: '#27ae60',
borderWidth: 1,
borderRadius: 1
},
{
label: '12 mill',
data: LOAN_DIST.from1to2M,
backgroundColor: '#e67e22cc',
borderColor: '#e67e22',
borderWidth: 1,
borderRadius: 1
},
{
label: '23 mill',
data: LOAN_DIST.from2to3M,
backgroundColor: '#e74c3ccc',
borderColor: '#e74c3c',
borderWidth: 1,
borderRadius: 1
},
{
label: 'Over 3 mill',
data: LOAN_DIST.over3M,
backgroundColor: '#8b1a1acc',
borderColor: '#8b1a1a',
borderWidth: 1,
borderRadius: 1
}
]
},
options: chart2Opts
});
// --- Diagram 3: Eierskap etter livssituasjon (horisontal stablet) ---
var chart3Opts = baseOpts();
chart3Opts.indexAxis = 'y';
chart3Opts.scales = {
x: {
stacked: true,
max: 100,
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, callback: v => v + ' %' },
grid: { color: GRID_COLOR },
border: { dash: [3, 3], color: 'transparent' }
},
y: {
stacked: true,
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, autoSkip: false },
grid: { display: false },
border: { color: 'rgba(0,0,0,0.1)' }
}
};
chart3Opts.plugins.tooltip = {
mode: 'index',
callbacks: {
label: function(c) {
return ' ' + c.dataset.label + ': ' + fmtPct(c.parsed.x);
}
},
backgroundColor: '#1a1714',
titleColor: '#f5f2eb',
bodyColor: 'rgba(245,242,235,0.7)',
padding: 10,
cornerRadius: 4,
titleFont: { family: 'DM Sans', size: 12 },
bodyFont: { family: 'DM Sans', size: 12 }
};
new Chart(document.getElementById('chart3'), {
type: 'bar',
data: {
labels: HOUSEHOLD_TYPES.map(h => h.name),
datasets: [
{
label: 'Selveier',
data: HOUSEHOLD_TYPES.map(h => h.selveier),
backgroundColor: '#2c6e49cc',
borderColor: '#2c6e49',
borderWidth: 1,
borderRadius: 2
},
{
label: 'Andelseier',
data: HOUSEHOLD_TYPES.map(h => h.andel),
backgroundColor: '#1a4a8acc',
borderColor: '#1a4a8a',
borderWidth: 1,
borderRadius: 2
},
{
label: 'Leier',
data: HOUSEHOLD_TYPES.map(h => h.leier),
backgroundColor: '#c0392bcc',
borderColor: '#c0392b',
borderWidth: 1,
borderRadius: 2
}
]
},
options: chart3Opts
});