Overview of registers

Variable names for the most commonly used DST registers

Published

October 1, 2026

A starting point, not an authority. This page can be out of date or simply wrong, and your own delivery may differ from it. Verify against your files with colnames() (see Phase 7 - Inspect your data) before you rely on anything here. Found a mistake? Open an issue or use the feedback box at the bottom - corrections are genuinely welcome.

Where this comes from, and why it can still be wrong

The tables on this page are generated from a schema built out of DST’s published documentation: the variable list for each register and DST’s order list, which names every variable in every DST register with its period. The health registers - LPR, LMDB, the death registers, the cancer register - are documented by Sundhedsdatastyrelsen on esundhed.dk instead, which is also the only source that publishes data types.

Each register links to its own source, and every value set says underneath where its codes come from.

Those sources change. Registers are extended, columns are added and retired, and a code can change meaning without changing its name. Names here are shown after rename_with(tolower), and your own delivery may spell them differently or not contain them at all: what DST documents is the register, not what your project ordered.

Key columns - the ones you actually use in the code - are marked in bold. Names apply after rename_with(tolower). See Pitfalls for the quirks of each register.

How to read the code examples: read_register() vs open_dataset()

The code on this page opens registers with read_register("registername") (fastreg, by name - recommended). That requires fastreg set up with the path to your registers, see Parquet and fastreg if you did not convert them from SAS yourself.

Without fastreg, use open_dataset("path/to/register/") instead and replace the path with your project’s parquet folder. Everything else in the examples works the same either way.

Looking for a particular variable? Find a variable searches every column in every register at once - the way to see how the same thing is named and coded differently from one register to the next.

Where to look things up

This page shows the columns most studies use. When you need more than that, the question you are asking decides where to go:

Your question Where to look
What are all the columns in this register? The register’s own variable list - follow the register name in the table below
Does this register reach the end of my follow-up? Datasafari - shows the latest reference date and the next expected update
Which registers exist at all, and which are closed? Oversigt over registre - over a thousand, with years covered. Luk means closed and never extended, as dodsaars and dodsaasg both are
Can I even order this variable, and for which years? Bestillingsliste.xlsx - every variable in every DST register, with its period. The one to open while you are still planning
What does code 330 mean? Klassifikationer - DISCED-15 for education, SOCIO for employment, DISCO for occupation
Why does this variable jump in one particular year? Højkvalitetsdokumentation - breaks in the series and validity periods, for selected variables
What does DST mean by “beskæftiget”? Hvad betyder - the words, not the columns. Look here when a variable measures something narrower than the everyday word suggests

All of it hangs off Dokumentation af data →, DST’s own hub, if you would rather start there. The health registers are documented separately by Sundhedsdatastyrelsen on esundhed.dk.

And whichever you use: what DST holds is not what your project was delivered. Confirm against your own files with colnames().

Overview - all registers

Register Read as Join key Period Often used
AKM "akm" pnr 1976 to 2024 socio13, socio02, socio
BEF "bef" pnr 1985-12 to 2026-06 koen, foed_dag, familie_id
CANCER "cancer" k_cprnr 1943 to 2024 c_icd10, c_morfo03, c_topo3
DOD "dod" pnr 1970 to 2025 doddato
DODSAARS "dodsaars" pnr 1970 to 2001 d_dodsdto, c_dodsmaade, c_dod1
DODSAARSAGER "dodsaarsager" pnr 2022 to 2024 doedsdato, doedsaarsag_tilgrundliggende, doedsaarsag_kode_1
DODSAASG "dodsaasg" pnr 2002 to 2022 d_dodsdato, c_dodtilgrundl_acme, c_dod_1a
FAIK "faik" familie_id 1987 to 2024 pnr, famaekvivadisp_13, year
FTBARN "ftbarn" PNR 1973 to 2023 FOED_DAG, LEVENDE_ELLER_DOEDFOEDT
FTFORAEL "ftforael" PNR 1973 to 2023 FORAELDER_PNR, MOR_FAR
FTNAEVN "ftnaevn" PNR, AAR 1973 to 2023
LAB_DM_FORSKER "lab_dm_forsker" patient_cpr 2008 to 2025 samplingdate, analysiscode, value
LMDB "lmdb" pnr 1995-12 to 2025-12 eksd, atc, atc1
LPR_A_DIAGNOSE "lpr_a_diagnose" dw_ek_kontakt 2019 to 2025 diag_kode, diag_kode_type, senere_afkraeftet
LPR_A_KONTAKT "lpr_a_kontakt" dw_ek_kontakt 2017 to 2025 dw_ek_forloeb, pnr, kont_starttidspunkt
LPR_A_PROCREGISTRERING "lpr_a_procregistrering" dw_ek_kontakt 2019 to 2025 proc_kode, proc_starttidspunkt, proc_kode_type
LPR_ADM "lpr_adm" recnum 1977 to 2019-03 pnr, d_inddto, d_uddto
LPR_DIAG "lpr_diag" recnum 1977 to 2019-03 c_diag, c_diagtype, c_tildiag
LPR_SKSOPR "lpr_sksopr" recnum 1996 to 2019 c_opr, c_oprart, c_osgh
LPR_SKSUBE "lpr_sksube" recnum 1999 to 2019 c_opr, d_odto, year
MFR "mfr" cpr_barn 1997 to 2018 alder_moder, bmi_moder, cpr_moder
MFR_NYFOEDTE "mfr_nyfoedte" CPRnummer_Barn 2019 to 2026 DW_EK_Nyfoedt, LevendefoedtDoedfoedt, FoedselsDato_Barn
SSSY "sssy" pnr 2005 to 2025 ydernr, speciale, ydlant
SYSI "sysi" pnr 1990 to 2005 ydernr, speciale, ydlant
T_PSYK_ADM "t_psyk_adm" recnum 1995 to 2019 pnr, c_pattype, c_adiag
T_PSYK_DIAG "t_psyk_diag" recnum 1995 to 2019 c_diag, c_diagtype, c_tildiag
UDDA "udda" pnr 1980-12 to 2025-09 hfaudd, udd, hf_vfra
VNDS "vnds" pnr 1973 to 2024 indud_kode, haend_dato, indud_land
VNDS_HIST "vnds_hist" pnr 1973 to 2004 indud_kode, haend_dato, indud_land
VNDS_IND "vnds_ind" pnr 2005 to 2025 haend_dato, indv_land, indvmd
VNDS_UD "vnds_ud" pnr 2005 to 2025 haend_dato, udv_land, udvmd

60 further satellite/detail registers exist and are fully documented, but are not listed here to keep this table to what most projects actually need first. Look them up by name or by column on Find a variable instead.

The Often used column is the handful of columns most studies reach for, not the full list: follow the register link for every column DST documents, or the section below for the ones this guide explains. lab_dm_forsker is in the schema but not in this table, because it is reached through Sundhedsdatastyrelsen’s Forskerservice rather than DST.

1. Demographics and deaths

BEF - Population Register

Status register - one snapshot per person per reference time point. Delivered quarterly since 2008 (March, June, September, December); before 2008 December only. Whether year == 2020 corresponds to a particular reference time point depends on the project convention - confirm in your project guide. A person who dies during 2020 still appears in the 2020 snapshot - use DOD to determine whether a person was alive on a specific date.

BEF cannot on its own answer whether a person was resident in Denmark on a given date: between two snapshots people can both leave and come back. To decide residence on an index date, combine BEF with VNDS - see Phase 10 - the source population.

Column Type Role Label Years
pnr character join key Personal identifier 1985 to 2026
koen numeric code Sex 1985 to 2026
foed_dag date date Date of birth 1985 to 2026
familie_id character join key Household key 1985 to 2026
reg character code Region 1985 to 2026
civst character code Marital status 1985 to 2026
kom character code Municipality code 1985 to 2026
year integer date Register year
alder numeric value Age at the reference time point 1985 to 2026
opr_land numeric code Country of origin 1985 to 2026
referencetid date date Reference time point 1985 to 2026
All other columns (30)
Column Type Role Label Years
mor_id character identifier Mother’s person id 1985 to 2026
far_id character identifier Father’s person id 1985 to 2026
aegte_id character identifier Spouse id 1985 to 2026
e_faelle_id character identifier Cohabiting partner id 1985 to 2026
fdato date date Date of birth, CPR form
antboernf numeric value Number of children in the family 1985 to 2026
antboernh numeric value Number of children in the household 1985 to 2026
antpersf numeric value Number of people in the family 1985 to 2026
antpersh numeric value Number of people in the household 1985 to 2026
antefam numeric value Number of E-families in the household 1985 to 2026
familie_type numeric code Family type 1985 to 2026
fam_koen numeric code Sex of the family’s reference person 1985 to 2026
plads numeric code Position in the family 1985 to 2026
hustype numeric code Household type 1985 to 2026
fm_mark numeric code Parent marker 1985 to 2026
civ_vfra date date Date the marital status took effect 1985 to 2026
bop_vfra date date Date of moving in or immigrating 1985 to 2026
ie_type numeric code Immigrant, descendant or Danish origin 1985 to 2026
foedreg_kode numeric code Place of birth registration 1985 to 2026
statsb numeric code Citizenship 1985 to 2026
opholdmd_dk numeric value Months of residence in Denmark 1985 to 2026
van_vtil date date Immigration date 1985-12 to 2003-12
foerste_indvandring date date First immigration date 2004-12 to 2026-06
seneste_indvandring date date Most recent immigration date 2004-12 to 2026-06
adresse_id character identifier Address id 1985 to 2026
fkirk character code Membership of the Danish National Church 2004-12 to 2026-06
cprtjek character code CPR check 2004-12 to 2026-06
cprtype character code CPR type 2004-12 to 2026-06
version numeric code Module data version 2004-12 to 2026-06
betalingskom character code Betalingskommune 1985 to 2026
  • mor_id: A pnr-like identifier for the mother, so BEF can be turned into a family structure without a separate register. It is only filled where the link is registered, which is not the case for everyone born before CPR.
  • fdato: Not on DST’s variable list for BEF, which documents foed_dag instead. Present in this delivery. Prefer foed_dag unless you have checked what yours contains.
  • antefam: A household can hold several families. That is why the family counts and the household counts differ, and why FAIK’s household income cannot be read as one family’s income without checking this.
  • van_vtil: Ends December 2003 and is replaced by foerste_indvandring and seneste_indvandring. A study spanning 2003 has to read both, or it silently loses immigration dates on one side of the break.
  • foerste_indvandring: Begins December 2004. Before that the information is in van_vtil.
  • adresse_id: Identifies a dwelling, so two people with the same value live at the same address. It is not a geographic coordinate and cannot be decoded into one.

No published source gives a data type for 1 of these 41 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • familie_id joins to FAIK (many-to-one).
Value sets for the coded columns (9)
Code system Values
koen 1 Mand, 2 Kvinde, 9 Uoplyst
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
civst U Ugift, G Gift (+ separeret), F Skilt, E Enke/Enkemand, P Registreret partnerskab, O Ophævet partnerskab, L Længstlevende af 2 partnere, D Død, 9 Uoplyst civilstand
kom Not listed here - see DST’s classification
familie_type 1 Ægtepar, 2 Registreret partnerskab, 3 Samlevende par, 4 Samboende par, 5 Enlig (herunder også ikke hjemmeboende børn), 7 Ægtepar forskellig køn, 8 Ægtepar samme køn, 9 Enlig, 10 Ikke hjemmeboende børn
plads 1 Hovedperson, 2 Ægtefælle/partner, 3 Hjemmeboende barn
hustype 1 Enlig mand, 2 Enlig kvinde, 3 Ægtepar, 4 Par i øvrigt, 5 Ikke hjemmeboende børn (under 18 år), 6 Andre husstande bestående af flere familier
fm_mark 1 Bor sammen med begge forældrene, 2 For børn: Bor hos mor, der er i nyt par. For voksne: Bor sammen med mor, 3 For børn: Bor hos enlig mor. For voksne: Værdien findes ikke, 4 For børn: Bor hos far, der er i nyt par. For voksne: Bor sammen med far, 5 For børn: Bor hos enlig far. For voksne: Værdien findes ikke, 6 Bor ikke hos forældrene
herkomst 1 Personer med dansk oprindelse, 2 Indvandrere, 3 Efterkommere, 9 Uoplyst
  • koen: DST’s classification KOEN_V1_1980 also defines 9 for not stated, which a delivery may not contain but a value set should. Sex is taken from the tenth digit of the CPR number: even is female, odd is male.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.
  • civst: Codes P, O and L came in with the registered-partnership act of 1 October 1989; before that the set was smaller. Registered partnerships could no longer be entered into from 15 June 2012.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • familie_type: There is no code 6, and the set changed in December 2015. Codes 7 and 8 split the old “Ægtepar” by sex, and codes 9 and 10 split the old “Enlig”, which had included children not living at home. A series that crosses 2015 therefore changes composition without any code going missing: 1 and 5 stop being used and four new codes appear. The exact switch-over dates are on DST’s page and should be read there before a study is dated around them.
  • fm_mark: Codes 3 and 5 occur for children only. For an adult the value does not exist, so an adult cohort holding them means the row is not what you think.
  • herkomst: A descendant is born in Denmark: neither parent is both a Danish citizen and born in Denmark. So the category says something about the parents, not about where the person was born, and it does not change over a lifetime the way citizenship does.

Where these values come from:

Worth knowing:

  • pnr: A person appears once per snapshot, not once in total. Taking a single year loses people who were resident but not in that particular snapshot, so a population is built from the union of all snapshots in the window.
  • year: Not a DST variable. It comes from the parquet conversion, which concatenates the yearly deliveries, so it exists in the data you read but not in DST’s own documentation of BEF. Because it is made rather than delivered, the name is not guaranteed: check colnames() rather than assuming.
  • alder: Age at the snapshot, not at any date you choose. Recompute from foed_dag and your own index date rather than reusing it.
  • referencetid: The date the snapshot describes. Every other column in the row is a status as of this moment, which is what makes BEF a status register rather than an event register.

BEF does not contain date of death. Use DOD (doddato) for censoring, not DODSAARS, which stops in 2001 (see below). DST’s own documentation: statistikdokumentation/befolkningen →.

DOD - Death Register

Døde i Danmark. One row per deceased person, covering 1970-2025 and still updated (DST register overview, last reference date 31 December 2025). This is the register you use to censor at death. It is a short one:

Column Type Role Label
pnr character join key Personal identifier
doddato date date Date of death
All other columns (3)
Column Type Role Label
alder_haend integer value Age at the time of death
cprtjek character value CPR check
cprtype character value CPR type

No published source gives a data type for 5 of these 5 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).

Worth knowing:

  • doddato: This is the column to censor on. Not d_dodsdto, which belongs to DODSAARS and stops in 2001.
DOD may not be in parquet on your project

DOD is sometimes delivered only as a raw SAS file, in which case read_register("dod") will not find it and you read it with haven::read_sas() instead. Ask your data manager for the path. And check the span of your own delivery, which is the years your project ordered rather than everything DST holds:

dod %>% summarise(min(doddato), max(doddato)) %>% collect()

DODSAARS - Cause of Death Register (ends 2001)

Dødsårssagsregistret. One row per deceased person, with the cause of death. It carries a death date too, in d_dodsdto, which is why it is so often used for censoring - but its coverage stops on 31 December 2001. Use it for causes of death up to 2001, and use DOD for the date.

Censoring on dodsaars silently treats everyone who died after 2001 as alive. No error, no warning: they simply stay in your risk set to the end of follow-up, so survival looks better than it is and rates come out too low. The full version of this is pitfall 1 - three death registers.

Column Type Role Label
pnr character join key Personal identifier
d_dodsdto date date Date of death
c_dodsmaade character code Manner of death
c_dod1 character code Underlying cause of death
c_dod2 character code Contributing cause of death 2
c_dod3 character code Contributing cause of death 3
c_dod4 character code Contributing cause of death 4
year integer date Register year
All other columns (27)
Column Type Role Label
c_dodskom character code Municipality of death
c_attart character code Type of certificate
c_sex character code Sex
v_alder numeric value Age at death
daar integer date Year of death
c_bopkom character code Municipality of residence at death
c_handsted character code Place of the event
c_liste_14 character code Cause group, 14-item list
c_liste_49 character code Cause group, 49-item list
c_liste_65 character code Cause group, 65-item list
cprtjek character code CPR check
cprtype character code CPR type
c_aldertim numeric value Age at death in hours
c_atckode1 character code Medicine code 1 (ATC)
c_atckode2 character code Medicine code 2 (ATC)
c_atckode3 character code Medicine code 3 (ATC)
c_atckode4 character code Medicine code 4 (ATC)
c_civstd character code Marital status
c_institut character code Place of death for a natural death
c_obduktio character code Autopsy indication
c_operatio character code Surgery indication
c_u28dg numeric value Death under 28 days of age
c_ulyktype character code Type of accident
v_aldermdr numeric value Age in months
v_bopamt numeric value County of residence
v_dodsamt numeric value County of death
v_klok numeric value Time of death
  • c_attart: Sundhedsdatastyrelsen gives it for 1971-1996 and 2000 only.
  • c_aldertim: Only 1980-1996 per Sundhedsdatastyrelsen. 1980 differs from the other years: besides the values 0-9 it holds values above 10.
  • c_atckode1: Only filled in 1999-2001.
  • c_atckode2: Only filled in 1999-2001.
  • c_atckode3: Only filled in 1999-2001.
  • c_atckode4: Only filled in 1999-2001.
  • c_obduktio: Sundhedsdatastyrelsen gives it for 1971-1996 and 1998-2001, so 1997 is missing.
  • c_u28dg: Only 1977-1996 per Sundhedsdatastyrelsen.
  • c_ulyktype: Only 1977-1993 per Sundhedsdatastyrelsen.

DST publishes no labels for 4 of these columns. Where the Label column is filled in anyway, it is this guide’s reading of the column name, not an official description.

No published source gives a data type for 29 of these 35 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (5)
Code system Values
c_dodsmaade 1 Naturlig død, 2 Ulykke, 3 Selvmord, 4 Drab/vold, 5 Uoplyst
kom Not listed here - see DST’s classification
icd10 Not listed here - see DST’s classification
atc Not listed here - see DST’s classification
icd8 Not listed here - see DST’s classification
  • c_dodsmaade: Two separate traps. First, this code set is NOT the one used from 2002: in dodsaasg the same column holds c_dodsmaade_2002, where 1 is Voldshandling rather than Naturlig død. Second, code 4 changed meaning. It was Selvmord until 31 December 1990 and Drab/vold from 1 January 1991. dodsaars runs from 1970 to 2001 and so contains both, in one column, with nothing to tell them apart except the date of death. Reading code 4 as one thing across the whole register counts homicides as suicides or the reverse. Codes 6 (Drab/vold) and 9 (Uoplyst) belong only to the old set and stop at the end of 1990; codes 3 and 5 only start in 1991.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • atc: As a rule, filter on the full 7-character code rather than on the level columns: atc2 holds three characters, so a longer pattern matched against it can never match, and it returns nothing at all with no error. The level columns are well suited to grouping, and to filtering when every code you want is the same length as the column.
  • icd8: A study whose period starts before 1994 is reading two classifications out of one column. ICD-10 codes match nothing in the early years, and the usual substr(c_diag, 2, 4) returns a meaningless fragment of an ICD-8 code rather than failing, so nothing tells you it went wrong.

Where these values come from:

Worth knowing:

  • d_dodsdto: A date of death exists here, but the register stops in 2001. Censor on DOD instead, which covers the whole period.
  • c_dod1: The underlying cause. Coded in the ICD revision in force at the time of death, so the code system changes inside the register’s own lifetime.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

DODSAARSAGER - the current register (2022 onwards)

Column Type Role Label
pnr character join key Personal identifier
doedsdato date date Date of death
doedsaarsag_tilgrundliggende character code Underlying cause of death
doedsaarsag_kode_1 character code Cause of death, code 1
doedsmaade_kode character code Manner of death
All other columns (34)
Column Type Role Label
doedsaarsag_liste_14_kode character code Cause group, 14-item list
doedsaarsag_liste_49_kode character code Cause group, 49-item list
doedssted_kode character code Place of death
dw_ek_borger character code Citizen key
flag_valideret character code Validated flag
borger_alder_doedsstatus numeric value
borger_bo_kom_doedsstatus character code
borger_bo_reg_doedsstatus character code
borger_koen_doedsstatus character code
cprtjek character code
cprtype character code
doedsaarsag_gruppering_a_kode character code
doedsaarsag_gruppering_b_kode character code
doedsaarsag_kode_2 character code
doedsaarsag_kode_3 character code
doedsaarsag_kode_4 character code
doedsaarsag_kode_a character code
doedsaarsag_kode_b character code
doedsaarsag_kode_c character code
doedsaarsag_kode_d character code
doedsstatusdato date date
doedssted_praecisering_kode character code
doedstidspunkt date date
findedato date date
findested_kode character code
findested_praecisering_kode character code
findetidspunkt date date
haendelsessted_kode character code
hospice character code
laegefunktion_kode character code
obduktionstype_kode character code
sygehus_org_reg character code
sygehus_shaksghkode character code
sygehus_sorkode character code
  • dw_ek_borger: An LPR3-style surrogate key alongside pnr. Not present in the two older cause-of-death registers.

DST publishes no labels for 10 of these columns. Where the Label column is filled in anyway, it is this guide’s reading of the column name, not an official description.

No published source gives a data type for 39 of these 39 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
icd10 Not listed here - see DST’s classification
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.

Where these values come from:

Every register in the chain renames the same thing. The cause columns are c_dod1 to c_dod4 here, c_dod_1a to c_dod_1d in DODSAASG from 2002, and doedsaarsag_kode_1 and so on in DODSAARSAGER from 2022. The date column goes d_dodsdto, d_dodsdato, doedsdato - one letter between the first two.

Code written for one part of the chain will not run against another, and a mistyped column name fails as a missing column rather than a wrong answer.

Cause of death is split across three registers, by period. dodsaars runs to 2001, dodsaasg covers 2002-2022, and dodsaarsager takes over from 2022. Each one stops where the next begins, so a study spanning more than one of those windows needs all the registers that overlap its period, chained together. A single one gives you a silently incomplete picture: causes simply stop appearing after its last year.

None of the three is the source for the date of death. For that, use DOD with the column doddato. The cause coding itself is documented by the Danish Health Data Authority: Dødsårsagsregisteret →.

Do you ever need both DOD and DODSAARS?

Only if your own DOD delivery does not reach back far enough for your study period. Then stack them, renaming so the date columns match, and note that the two registers overlap for 1970-2001 - so without the distinct() every early death is counted twice:

deaths <- bind_rows(
  dod %>% select(pnr, death_date = doddato),
  dodsaars %>% select(pnr, death_date = d_dodsdto)
) %>%
  mutate(death_date = as.Date(death_date)) %>%
  distinct(pnr, .keep_all = TRUE) # keeps the DOD row, since it comes first

On DARTER, see Register paths and datastores.

VNDS - Migration Register

One row per migration event per person.

VNDS was closed in February 2026 and split into three registers (VNDS_ind, VNDS_ud, VNDS_hist, described below). It is still documented here because it is the only migration register many projects have: a delivery made before the split will not contain the replacements.

Check colnames() or your project’s register list to see which you have. If you have both, use the new ones and do not mix them with VNDS, or you will count the same migration twice. For emigration dates used in censoring, combine VNDS_ud (2005+) and VNDS_hist (1973-2004) in place of the old VNDS.

What the three replacement registers are, and why DST split them
  • VNDS_ind: immigrations to Denmark from 2005 onwards.
  • VNDS_ud: emigrations from Denmark from 2005 onwards.
  • VNDS_hist: historical migrations 1973-2004, no longer updated.

The split reduces duplicates that arose because immigration and emigration data came from different sources over the years. The earliest data is now frozen in the historical register. Source: DST notice, 19 February 2026.

Column Type Role Label
pnr character join key Personal identifier
indud_kode character code Immigration or emigration
haend_dato date date Date of the migration event
indud_land character code Country migrated from or to
All other columns (2)
Column Type Role Label
cprtjek character value CPR check
cprtype character value CPR type

No published source gives a data type for 6 of these 6 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
indud_kode I Indvandring, U Udvandring
  • indud_kode: Use U for censoring at emigration. People who never emigrated have no U event at all, so they are simply absent rather than carrying a missing date. Two caveats from the guide: CPR only has complete immigration and emigration data from 1971, so someone who immigrated before that has no event and looks resident since birth; and a move to Greenland is a status of its own in CPR rather than an emigration. Confirm the values on your own delivery.

Where these values come from:

Worth knowing:

  • indud_land: Not listed in the guide’s own table. The country code set has not been sourced.

Use: filter(indud_kode == "U") → min(haend_dato) per pnr for first emigration date. Non-emigrants do not appear in VNDS with a “U” event and get emigration_date = NA.

VNDS_hist - historical migrations (1973-2004)

Column Type Role Label
pnr character join key Personal identifier
indud_kode character code Immigration or emigration
haend_dato date date Date of the migration event
indud_land character code Country migrated from or to
All other columns (2)
Column Type Role Label
cprtjek character value
cprtype character value

No published source gives a data type for 6 of these 6 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
indud_kode I Indvandring, U Udvandring
  • indud_kode: Use U for censoring at emigration. People who never emigrated have no U event at all, so they are simply absent rather than carrying a missing date. Two caveats from the guide: CPR only has complete immigration and emigration data from 1971, so someone who immigrated before that has no event and looks resident since birth; and a move to Greenland is a status of its own in CPR rather than an emigration. Confirm the values on your own delivery.

Where these values come from:

VNDS_ind - immigrations (2005 onwards)

The two new registers drop indud_kode: which direction the event went is now carried by which register you are reading, so a combined series has to add the direction back itself.

Column Type Role Label
pnr character join key Personal identifier
haend_dato date date Date of immigration
indv_land character code Country immigration from
indvmd character date Month of immigration
All other columns (18)
Column Type Role Label
adresse_id character code
alder_haend integer value
alder_ult integer value
bank_statsb character code
civst character code
cprtjek character value
cprtype character value
foedreg_kode character code
foed_dag date date
foed_land character code
ie_type character code
koen integer code
kom character code
opr_land character code
referencetid date date
reg character code
statsb character code
version character value
  • adresse_id: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • alder_haend: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • alder_ult: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • bank_statsb: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • cprtjek: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • cprtype: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foedreg_kode: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foed_dag: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foed_land: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • ie_type: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • opr_land: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • referencetid: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • statsb: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • version: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.

No published source gives a data type for 22 of these 22 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (5)
Code system Values
civst U Ugift, G Gift (+ separeret), F Skilt, E Enke/Enkemand, P Registreret partnerskab, O Ophævet partnerskab, L Længstlevende af 2 partnere, D Død, 9 Uoplyst civilstand
ie_type 1 Dansk, 2 Indvandrere, 3 Efterkommere, 9 Uoplyst
koen 1 Mand, 2 Kvinde, 9 Uoplyst
kom Not listed here - see DST’s classification
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
  • civst: Codes P, O and L came in with the registered-partnership act of 1 October 1989; before that the set was smaller. Registered partnerships could no longer be entered into from 15 June 2012.
  • ie_type: DST’s current high-quality page for IE_TYPE states that the variable has no value set. The codes here come from the older TIMES3 archive page, which does publish them.
  • koen: DST’s classification KOEN_V1_1980 also defines 9 for not stated, which a delivery may not contain but a value set should. Sex is taken from the tenth digit of the CPR number: even is female, odd is male.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.

Where these values come from:

VNDS_ud - emigrations (2005 onwards)

Column Type Role Label
pnr character join key Personal identifier
haend_dato date date Date of emigration
udv_land character code Country emigration to
udvmd character date Month of emigration
All other columns (18)
Column Type Role Label
adresse_id character code
alder_haend integer value
alder_ult integer value
bank_statsb character code
civst character code
cprtjek character value
cprtype character value
foedreg_kode character code
foed_dag date date
foed_land character code
ie_type character code
koen integer code
kom character code
opr_land character code
referencetid date date
reg character code
statsb character code
version character value
  • adresse_id: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • alder_haend: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • alder_ult: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • bank_statsb: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • cprtjek: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • cprtype: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foedreg_kode: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foed_dag: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • foed_land: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • ie_type: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • opr_land: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • referencetid: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • statsb: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.
  • version: DST’s variable list gives this column no label, so the schema records the name only. Its meaning has not been sourced.

No published source gives a data type for 22 of these 22 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (5)
Code system Values
civst U Ugift, G Gift (+ separeret), F Skilt, E Enke/Enkemand, P Registreret partnerskab, O Ophævet partnerskab, L Længstlevende af 2 partnere, D Død, 9 Uoplyst civilstand
ie_type 1 Dansk, 2 Indvandrere, 3 Efterkommere, 9 Uoplyst
koen 1 Mand, 2 Kvinde, 9 Uoplyst
kom Not listed here - see DST’s classification
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
  • civst: Codes P, O and L came in with the registered-partnership act of 1 October 1989; before that the set was smaller. Registered partnerships could no longer be entered into from 15 June 2012.
  • ie_type: DST’s current high-quality page for IE_TYPE states that the variable has no value set. The codes here come from the older TIMES3 archive page, which does publish them.
  • koen: DST’s classification KOEN_V1_1980 also defines 9 for not stated, which a delivery may not contain but a value set should. Sex is taken from the tenth digit of the CPR number: even is female, odd is male.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.

Where these values come from:

2. LPR2 - Somatic (up to March 2019)

The register itself is owned by the Danish Health Data Authority, whose documentation covers what is reported and how it changed over time: Landspatientregisteret →.

Join: lpr_adm LEFT JOIN lpr_diag ON recnum.

lpr_adm - Contacts

Column Type Role Label Years
recnum character join key Contact identifier 1977 to 2019
pnr character identifier Personal identifier 1977 to 2019
d_inddto date date Date of admission 1977 to 2019
d_uddto date date Date of discharge 1977 to 2019
c_pattype character code Patient type 1977 to 2019
c_spec character code Specialty 1977 to 2019
c_adiag character code Action diagnosis 1977 to 2019
c_indm character code Admission mode 1977 to 2019
year integer date Register year
All other columns (43)
Column Type Role Label Years
c_sgh character code Hospital 1977 to 2019
c_afd character code Department 1977 to 2019
v_alder numeric value Age at the start of the contact 1977 to 2019
c_udm character code Discharge mode 1987 to 2019
c_henm character code Referral mode 1987 to 2019
c_kontaars character code Reason for the contact 1987 to 2019
c_bopamt character code County of residence 1977 to 2004
c_amt character code County 2005 to 2019
v_sengdage numeric value Bed days 1994 to 2019
v_behdage numeric value Treatment days 1977 to 2019
c_sex character code Sex 1977 to 2019
cprtjek character code CPR check 1977 to 2019
cprtype character code CPR type 1977 to 2019
c_andenbeh character code Planned other treatment 1977 to 1986
c_blok character code Specialty block 1994 to 2019
c_eakt character code Activity at the time of the accident 1987 to 2003
c_emek character code Accident mechanism 1987 to 2003
c_emodpart character code Mode of transport of the counterpart in a traffic accident 1994 to 2003
c_epart character code Injured person’s mode of transport in a traffic accident 1994 to 2003
c_ested character code Place of accident 1987 to 2003
c_etraf character code Traffic accident or not 1987 to 2003
c_hafd character code Referring department 2004 to 2019
c_hsgh character code Referring hospital 2004 to 2019
c_indform character code Form of admission 1977 to 1986
c_indfra character code Where the patient was admitted from 1977 to 1986
c_kom character code Patient’s municipality of residence 1977 to 2019
c_nyafd character code 2005 to 2019
c_senstat character code Planned later inpatient treatment 1977 to 1986
c_sghamt character code Hospital county 1977 to 2019
c_udtil character code Where the patient was discharged to 1977 to 1986
c_ulykke character code Accident code (1977-1986) 1977 to 1986
d_ebhdto date date Date of final treatment 1996 to 2019
d_fusdto date date Date of preliminary examination 1996 to 2019
d_hendto date date Referral date 1977 to 2019
d_opdatdto date date Internal date the contact was last updated 2005 to 2019
k_afd character code Department code 2005 to 2019
leverancedato date date 1977 to 2019
version character code Version 1977 to 2019
v_alddg numeric value Age in days at the start of the contact 2001 to 2019
v_aldmdr numeric value Age in months at the start of the contact 2001 to 2019
v_indminut numeric value Minute the contact started 1994 to 2019
v_indtime numeric date Hour the contact started 1977 to 2019
v_udtime numeric value Hour the contact ended 1994 to 2019
  • c_udm: Starts in 1987, ten years after the register itself.
  • c_henm: Codes change twice: in 1999 code 6 was replaced by B, C and D, and in 2004 codes 3, 5, B, C and D were replaced by F and G.
  • c_bopamt: Ends with the counties themselves: the 2007 local government reform is already visible here in 2004/2005, where c_bopamt stops and c_amt starts. Neither covers the whole register, so a geographic analysis spanning that point needs both.
  • v_sengdage: Starts in 1994. Before that, compute the stay from d_inddto and d_uddto instead.
  • v_behdage: Ends in 2001.
  • c_sex: The coding changes in 2005, from 1/2 to M/K. Prefer koen from BEF for a study variable.
  • c_eakt: Until 1994 it only records whether the accident was a work accident (1 or 2); the code set was widened to other activities from 1995.
  • c_emodpart: Sundhedsdatastyrelsen gives this from 1995, a year later than DST’s variable list.
  • c_epart: Sundhedsdatastyrelsen gives this from 1995, a year later than DST’s variable list.
  • c_kom: A finer subdivision briefly existed below municipality level: LPR2 had its own table, LPR_DISTKOD, giving a social district (socialdistrikt) for residents of large municipalities only, 1995-2003. Not modelled as a separate register here (per Sundhedsdatastyrelsen’s own LPR documentation, esundhed.dk table t_distkod) - only relevant to a study needing sub-municipality geography for that narrow window and population. Municipality codes changed substantially at the 2007 reform, and old codes can still appear on contacts that started after 2007.
  • d_ebhdto: DST’s label says it was discontinued after 31 December 2003, and Sundhedsdatastyrelsen gives it for 1999-2003 only.
  • d_fusdto: DST’s label says it was discontinued after 31 December 2003; Sundhedsdatastyrelsen gives it for 1994-2003.
  • d_opdatdto: Before 2005, the same fact (a contact’s last-update date) lived in its own table, LPR_OPDTDTO, covering 2000-2004 - not modelled as a separate register here since Sundhedsdatastyrelsen’s own LPR documentation (esundhed.dk, table t_opdatdto) confirms the fact simply moved onto lpr_adm from 2005 onward. A study needing this fact before 2005 has no column to read it from; DST’s order list shows no earlier source. From 2005. Sundhedsdatastyrelsen keeps the update dates for 2000-2004 in a separate table (t_opdatdto).

No published source gives a data type for 20 of these 52 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to LPR_DIAG (one-to-many).
Value sets for the coded columns (21)
Code system Values
pattype 0 Heldoegnspatient (to 2001), Indlagt patient (2002-), 1 Dagpatient (to 1986), Deldoegnspatient (1987-2001), 2 Natpatient (to 1986), Ambulant patient (1987-), 3 Skadestuepatient
icd10_sks Not listed here - see DST’s classification
indm 1 Akut, 2 Ikke akut, 9 Uoplyst
c_udm 1 Udskrevet/afsluttet til alment praktiserende læge, 2 Udskrevet/afsluttet til praktiserende speciallæge, 3 Udskrevet/afsluttet til eget heldøgnsafsnit eller eget deldøgnsafsnit, 4 Ingen lægelig opfølgning (må kun anvendes for psykiatriske afdelinger), 5 Udskrevet/afsluttet til andet heldøgnsafsnit eller andet deldøgnsafsnit, 6 Udskrevet/afsluttet til ambulatorium, 7 Udeblevet (kun ambulante patienter), 8 Død, 9 Uoplyst, A Andet, B Udskrevet/afsluttet til eget ambulatorium, C Udskrevet/afsluttet til andet ambulatorium, E Behandling i udlandet (hvor sygehus beslutter behandling i udlandet), F Afsluttet til sygehusafsnit, G Afsluttet til sygehusafsnit, venteforløb, K Afsluttet til sygehusafsnit (hjemmet), L Afsluttet til sygehusafsnit, venteforløb (hjemmet)
c_henm 0 Ingen henvisning, 1 Henvist fra alment praktiserende læge, 2 Henvist fra praktiserende speciallæge, 3 Henvist fra eget heldøgnsafsnit eller eget deldøgnsafsnit, 5 Henvist fra andet heldøgnsafsnit eller andet deldøgnsafsnit, 6 Henvist fra skadestue eller ambulatorium, 8 Herfødt, 9 Uoplyst, A Andet, B Eget ambulatorium, C Andet ambulatorium, D Skadestue, E Udlandet (kun direkte henvisninger), F Henvist fra sygehusafsnit, G Henvist fra sygehusafsnit, venteforløb
c_kontaars 1 Sygdom og tilstand uden direkte sammenhæng med udefra påført læsion, 2 Ulykke, 3 Voldshandling, 4 Selvmord/selvmordsforsøg, 5 Senfølge, 6 Komplet skaderegistrering foretages på efterfølgende kontakt, 7 Komplet skaderegistrering foretaget på tidligere kontakt, 8 Andet, 9 Uoplyst
sex_lpr 1 Mand (to 2004), 2 Kvinde (to 2004), M Mand (2005-), K Kvinde (2005-)
c_andenbeh 0 Ja, eget ambulatorium, 1 Ja, andet ambulatorium, eget sygehus, 2 Ja, andet ambulatorium, andet sygehus, 3 Ja, egen læge, 6 Ja, anden, 7 Ingen, 8 Død, 9 Uoplyst
c_blok 1 Medicinsk blok, 2 Kirurgisk blok, 5 Psykiatrisk blok, 6 Laboratorie blok, 8 Øvrige specialer, 9 Andre specialer, 99 Uden for specialer
c_eakt 1 Idræt, sport og motion, 2 Leg, hobby og and fritidsvirksomhed, 3 Erhvervsarbejde, 4 Vitalaktivitet, 5 Ulønnet arbejde, 8 Anden aktivitet, 9 Ikke specificeret aktivitet
c_emek 0 Slag, stød grundet fald på samme niveau, 1 Slag, stød grundet fald på trappe eller til lavere niveau, 2 Slag, stød grundet kontakt med anden genstand, person eller dyr, 3 Klemning, snit eller stik, 4 Fremmedlegeme, 5 Kvælning, 6 Kemisk påvirkning, 7 Termisk, elektrisk eller strålingspåvirkning, 8 Akut overbelastning af legeme eler legemesdel, 9 Anden og ukendt skadesmekanisme
c_emodpart 0 Ingen modpart, 1 Til fods, 2 Cykel, 3 Knallert, 4 Motorcykel eller scooter, 5 Personbil, 6 Varevogn, 7 Lastbil, bus, m.m., 8 Anden transportform, modpart, 9 Ikke specificeret transportform, modpart
c_epart 1 Til fods, 2 Cykel, 3 Knallert, 4 Motorcykel eller scooter, 5 Personbil, 6 Varevogn, 7 Lastbil, bus, m.m., 8 Anden transportform, tilskadekomne, 9 Ikke specificeret transportform, tilskadekomne
c_ested 0 Trafikområde, 1 Boligområde, 2 Produktions- og værkstedsområde, 3 Butiks- handels- og serviceområde, 4 Skole, offentlig administrations- og institutionsområde, 5 Idræts- og sportsområdet, 6 Forlystelses- og parkområdet, 7 Fri natur, 8 Hav, sø og vådområder, 9 Uoplyst
c_etraf 1 Færdselsuheld, 2 Ikke færdselsuheld
c_indform 0 Akut indlæggelse, 1 Indkaldt via forambulatorium, 2 Indkaldt via andet ambulatorium, 3 Anden indkaldelse, 4 Genindkaldt, 5 Indkaldt via koordineret forundersøgelse, 8 Herfødt, 9 Uoplyst
c_indfra 0 Hjemmet, 1 Hjemmet ekskl. døgnistitution, 2 Psykiatrisk hospital/sygehusafdeling, 3 Psykiatrisk dag/nathospital, 4 Somatisk afdeling, 5 Plejehjem/institution, 6 Andet, 8 Født her, 9 Uoplyst, A Andet
c_senstat 0 Ja, samme afdeling, 1 Ja, anden afdeling, 2 Ja, andet sygehus, 3 Ja, alderdoms- eller plejehjem, 5 Ja, rekreationshjem, 6 Ja, andre institutioner, 7 Ingen, 8 Død, 9 Uoplyst
c_udtil 0 Hjemmet, 1 Hjemmet ekskl. døgnistitution, 2 Psykiatrisk hospital/sygehusafdeling, 3 Psykiatrisk dag/nathospital, 4 Somatisk afdeling, 5 Plejehjem/institution, 6 Andet, 8 Død, 9 Uoplyst, A Andet
c_ulykke 0 Nej, 1 Ja, trafikulykke, 2 Ja, arbejdsulykke, 3 Ja, idrætsulykke, 4 Ja, hjemmeulykke, 5 Ja, anden ulykke, 6 Uoplyst, 7 Uoplyst
icd8 Not listed here - see DST’s classification
  • pattype: There are four codes, not six, and three of them changed meaning. Code 1 was Dagpatient until 1986 and Deldoegnspatient from 1987, and then stops entirely at the end of 2001. Code 2 was Natpatient until 1986 and Ambulant from 1987. Code 0 was Heldoegnspatient until 2001 and Indlagt patient from 2002. The register only started using 1, 2 and 3 in 1994, so before that essentially every contact is 0. Code 3 was discontinued at the end of 2013, and from 2014 an emergency-room visit arrives as 2 with an acute admission mode in c_indm. Reading 2 as outpatient across the whole register therefore mislabels night patients before 1987 and emergency visits after 2013.
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • indm: From 2014 this is what separates an emergency-room visit from an ordinary outpatient one, because c_pattype code 3 was discontinued and both arrive as 2. Code 9 (Uoplyst) stops at the end of 2003, so a missing value after that is genuinely missing rather than coded as unknown.
  • c_udm: Only codes 1, 8 and 9 reach back to 1987, and 9 stops in 2003. Discharge to another hospital unit is the trap: it was 3, 5, B or C until 2003 or 2004 and becomes F, G, K or L from 2004 onwards. Counting “discharged onwards to hospital” across the whole register therefore needs both sets, and either set alone gives a series with a hole in it. Codes 2, 4, 7 and A only begin in 1995, E in 2002, and K and L in 2006.
  • c_henm: Only four codes cover the whole register: 0, 1, 2 and 8. Everything else has a window. Codes 3, 5, 9, B, C and D stop at the end of 2003 and 6 stops at the end of 1998, while F and G only begin in 2004, A in 1995 and E in 2002. The end of 2003 is a break: referrals from a hospital unit were coded 3, 5, B, C or D before it and F or G after it. Counting any of those across the whole period gives a number that changes for administrative reasons alone.
  • c_kontaars: Code 4 was Selvtilføjet skade until the end of 1993 and Selvmord/selvmordsforsøg from 1994. Those are not the same population: self-inflicted injury is wider than an attempt at suicide, so a series that spans 1994 changes definition rather than changing level. Codes 5 and 9 stop at the end of 2013. Code 7 only starts in 2011 and code 6 only in 2014, so neither says anything about earlier contacts.
  • sex_lpr: The coding changed at the start of 2005: 1/2 until the end of 2004, M/K from 2005. A study spanning that year that filters on c_sex == "2" keeps only the women seen before 2005 and silently drops the rest, with no error and no empty result to warn you. Take sex from BEF instead, where it is koen coded 1/2 throughout, unless you specifically need what the hospital recorded.
  • c_andenbeh: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.1986.
  • c_eakt: 2 of the 7 codes were REUSED with a different meaning, so the same number does not mean the same thing across the register. The lookup above gives the current meaning; the periods block gives both. Code 1: arbejdsulykke, then idræt, sport og motion from 01.01.1995. Code 2: ikke arbejdsulykke, then leg, hobby og and fritidsvirksomhed from 01.01.1995. Every code in this variable stops by 31.12.2003, so it says nothing about later contacts.
  • c_emek: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.2003.
  • c_emodpart: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.2003.
  • c_epart: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.2003.
  • c_ested: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.2003.
  • c_etraf: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.2003.
  • c_indform: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.1986.
  • c_indfra: 4 of the 10 codes were REUSED with a different meaning, so the same number does not mean the same thing across the register. The lookup above gives the current meaning; the periods block gives both. Code 1: anden afdeling, then hjemmet ekskl. døgnistitution from 01.01.1995. Code 2: andet sygehus, then psykiatrisk hospital/sygehusafdeling from 01.01.1995. Code 3: alderdoms- eller plejehjem, then psykiatrisk dag/nathospital from 01.01.1995. Code 5: skadestue, then plejehjem/institution from 01.01.1995. Every code in this variable stops by 31.12.2000, so it says nothing about later contacts.
  • c_senstat: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.1986.
  • c_udtil: 4 of the 10 codes were REUSED with a different meaning, so the same number does not mean the same thing across the register. The lookup above gives the current meaning; the periods block gives both. Code 1: anden afdeling, then hjemmet ekskl. døgnistitution from 01.01.1995. Code 2: andet sygehus, then psykiatrisk hospital/sygehusafdeling from 01.01.1995. Code 3: alderdoms- eller plejehjem, then psykiatrisk dag/nathospital from 01.01.1995. Code 5: rekreationshjem, then plejehjem/institution from 01.01.1995. Every code in this variable stops by 31.12.2000, so it says nothing about later contacts.
  • c_ulykke: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.1986.
  • icd8: A study whose period starts before 1994 is reading two classifications out of one column. ICD-10 codes match nothing in the early years, and the usual substr(c_diag, 2, 4) returns a meaningless fragment of an ICD-8 code rather than failing, so nothing tells you it went wrong.

Where these values come from:

Worth knowing:

  • recnum: The key every other LPR2 dataset joins on. It identifies a contact, not a person.
  • d_inddto: Use this as the contact date. It is the admission date, so for an outpatient course it is the date the course started, not the date of a particular visit.
  • c_pattype: Until 1993 only patient type 0 (inpatient) was recorded. Day patient (1) was discontinued in 2002, and hospitals then recorded those patients differently (some as outpatients, some as inpatients). Emergency room patient (3) was discontinued in 2014 and replaced by outpatient (2) with acute admission (c_indm = 1).
  • c_spec: DST publishes what each specialty code means in its department and specialty overview: https://www.dst.dk/da/Statistik/dokumentation/Times/moduldata-for-sociale-forhold–sundhedsvaesen–retsvaesen/spec (in Danish). The codes are not self-explanatory, so look them up rather than grouping on the digits.
  • c_adiag: A copy of the contact’s action diagnosis. Use lpr_diag instead: it holds every diagnosis on the contact, not only the action one.
  • c_indm: Used together with c_pattype to separate emergency-room contacts from ordinary outpatient ones after about 2014, see the LPR extraction chapter. Available for the register’s whole span, so a missing c_indm is an extract boundary rather than a coverage gap.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

lpr_diag - Diagnoses

Column Type Role Label Years
recnum character join key Contact identifier 1977 to 2019
c_diag character code Diagnosis code 1977 to 2019
c_diagtype character code Diagnosis type 1977 to 2019
c_tildiag character code Supplementary diagnosis 1995 to 2019
year integer date Register year
All other columns (3)
Column Type Role Label Years
c_diagmod character code Diagnosis modification 1977 to 1994
leverancedato date date 1977 to 2019
version character code Version 1977 to 2019

No published source gives a data type for 5 of these 8 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to LPR_ADM (many-to-one).
Value sets for the coded columns (4)
Code system Values
icd10_sks Not listed here - see DST’s classification
diagtype A Aktionsdiagnose, B Bidiagnose, G Grundmorbus, naar forskellig fra aktionsdiagnose, H Henvisningsdiagnose, M Midlertidig diagnose, kun for aabne somatisk ambulante besoeg, C Komplikation
c_diagmod 0 Ingen modifikation, 1 Obs. pro., 2 Ej befundet, 3 Sequelae, 4 Antea, 5 Recidivans, 6 Traktatus, 7 Operatus
icd8 Not listed here - see DST’s classification
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • diagtype: The guide long described this as an A/B/G column. There are six codes, and three of them stop: G runs 1995-2003 only, M 1998-2013 and C 2002-2013. A and B run the whole period, H from 1995. So a comorbidity definition built on G silently covers nine years and nothing else, and filtering to A/B/G drops referral diagnoses entirely. Which types to keep is a case definition, not a technicality: outcomes usually use A and B. Carry the type column into the extract so the definition can be varied later.
  • c_diagmod: Not every code covers the whole register. The periods block gives the window for each one; codes stop being used at 31.12.1986, 31.12.1994.
  • icd8: A study whose period starts before 1994 is reading two classifications out of one column. ICD-10 codes match nothing in the early years, and the usual substr(c_diag, 2, 4) returns a meaningless fragment of an ICD-8 code rather than failing, so nothing tells you it went wrong.

Where these values come from:

Worth knowing:

  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

3. LPR2 - Psychiatric (1995 – March 2019)

Psychiatric contacts before March 2019 are in separate registers from somatic LPR2. From March 2019, LPR3 covers both in one table.

Before 1995: inpatients only, and ICD-8

The Danish Psychiatric Central Register is electronic from 1969, but covers only inpatients until 1995 (outpatient visits were added from 1995), and diagnoses before 1994 are coded in ICD-8 (numeric codes, e.g. 290-315, where 290 covers dementia) - not ICD-10 F-codes. These older data are normally not part of the standard extract and are requested separately, via Rigsarkivet or NCRR, Aarhus University. If your study covers that period, you have to map ICD-8 to your F-code groups yourself.

If you forget to query the psychiatric registers for the period 1995–2019, you miss all dementia diagnoses (F00–F03) recorded at geriatric psychiatry outpatient clinics and memory clinics. Those patients will appear dementia-free and remain in the cohort as false negatives.

t_psyk_adm - Psychiatric contacts

The key and person columns may be renamed in your delivery. DST’s variable list gives both psychiatric tables RECNUM and PNR, the same names the somatic registers use. Several deliveries hand them over renamed: DARTER has k_recnum and v_cpr here, and v_recnum in the diagnosis table, so one key ends up with three names. That is data processing, not the register. Run colnames() first, and rename to recnum and pnr if yours differ:

library(fastreg) # read_register()
library(dplyr) # %>%, rename_with(), rename()

psyk_adm <- read_register("t_psyk_adm") %>%
  rename_with(tolower) %>%
  rename(pnr = v_cpr, recnum = k_recnum)
Column Type Role Label
pnr character join key Personal identifier
recnum character join key Contact identifier
c_pattype character code Contact type
c_adiag character code Primary diagnosis
d_inddto date date Admission date
d_uddto date date Discharge date
All other columns (32)
Column Type Role Label
c_indm character code Admission mode
c_udm character code Discharge mode
c_sgh character code Hospital
c_afd character code Department
c_spec character code Specialty
v_indtime integer value Admission hour
v_indminut integer value Admission minute
v_udtime integer value Discharge hour
cprtjek character code CPR check
cprtype character code CPR type
c_amt character code Patient’s county of residence
c_blok character code Specialty block
c_hafd character code Referring department
c_henm character code Referral mode
c_hsgh character code Referring hospital
c_kom character code Patient’s municipality of residence
c_kontaars character code Reason for contact
c_nyafd character code
c_sex character code Sex
c_sghamt character code Hospital county
d_ebhdto date date Date of final treatment
d_fusdto date date Date of preliminary examination
d_hendto date date Referral date
d_opdatdto date date Internal date the contact was last updated
k_afd character code Department code
leverancedato date date
version character code Version
v_alddg numeric value Age in days at the start of the contact
v_alder numeric value Age in years at the start of the contact
v_aldmdr numeric value Age in months at the start of the contact
v_behdage numeric value Treatment days
v_sengdage numeric value Bed days
  • c_amt: Called c_bopamt until 2005, when it was renamed c_amt; Sundhedsdatastyrelsen reports no break in the content.
  • c_henm: Codes change twice: in 1999 code 6 was replaced by B, C and D, and in 2004 codes 3, 5, B, C and D were replaced by F and G.
  • c_kom: Municipality codes changed substantially at the 2007 reform, and old codes can still appear on contacts that started after 2007.
  • c_sex: The coding changes in 2005, from 1/2 to M/K. Prefer koen from BEF for a study variable.
  • d_ebhdto: DST’s label says it was discontinued after 31 December 2003, and Sundhedsdatastyrelsen gives it for 1999-2003 only.
  • d_fusdto: DST’s label says it was discontinued after 31 December 2003; Sundhedsdatastyrelsen gives it for 1994-2003.
  • d_opdatdto: From 2005. Sundhedsdatastyrelsen keeps the update dates for 2000-2004 in a separate table (t_opdatdto).
  • v_behdage: DST’s label says it was discontinued after 31 December 2001.

No published source gives a data type for 6 of these 38 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to T_PSYK_DIAG (one-to-many).
Value sets for the coded columns (8)
Code system Values
pattype 0 Heldoegnspatient (to 2001), Indlagt patient (2002-), 1 Dagpatient (to 1986), Deldoegnspatient (1987-2001), 2 Natpatient (to 1986), Ambulant patient (1987-), 3 Skadestuepatient
icd10_sks Not listed here - see DST’s classification
indm 1 Akut, 2 Ikke akut, 9 Uoplyst
c_udm 1 Udskrevet/afsluttet til alment praktiserende læge, 2 Udskrevet/afsluttet til praktiserende speciallæge, 3 Udskrevet/afsluttet til eget heldøgnsafsnit eller eget deldøgnsafsnit, 4 Ingen lægelig opfølgning (må kun anvendes for psykiatriske afdelinger), 5 Udskrevet/afsluttet til andet heldøgnsafsnit eller andet deldøgnsafsnit, 6 Udskrevet/afsluttet til ambulatorium, 7 Udeblevet (kun ambulante patienter), 8 Død, 9 Uoplyst, A Andet, B Udskrevet/afsluttet til eget ambulatorium, C Udskrevet/afsluttet til andet ambulatorium, E Behandling i udlandet (hvor sygehus beslutter behandling i udlandet), F Afsluttet til sygehusafsnit, G Afsluttet til sygehusafsnit, venteforløb, K Afsluttet til sygehusafsnit (hjemmet), L Afsluttet til sygehusafsnit, venteforløb (hjemmet)
c_blok 1 Medicinsk blok, 2 Kirurgisk blok, 5 Psykiatrisk blok, 6 Laboratorie blok, 8 Øvrige specialer, 9 Andre specialer, 99 Uden for specialer
c_henm 0 Ingen henvisning, 1 Henvist fra alment praktiserende læge, 2 Henvist fra praktiserende speciallæge, 3 Henvist fra eget heldøgnsafsnit eller eget deldøgnsafsnit, 5 Henvist fra andet heldøgnsafsnit eller andet deldøgnsafsnit, 6 Henvist fra skadestue eller ambulatorium, 8 Herfødt, 9 Uoplyst, A Andet, B Eget ambulatorium, C Andet ambulatorium, D Skadestue, E Udlandet (kun direkte henvisninger), F Henvist fra sygehusafsnit, G Henvist fra sygehusafsnit, venteforløb
c_kontaars 1 Sygdom og tilstand uden direkte sammenhæng med udefra påført læsion, 2 Ulykke, 3 Voldshandling, 4 Selvmord/selvmordsforsøg, 5 Senfølge, 6 Komplet skaderegistrering foretages på efterfølgende kontakt, 7 Komplet skaderegistrering foretaget på tidligere kontakt, 8 Andet, 9 Uoplyst
sex_lpr 1 Mand (to 2004), 2 Kvinde (to 2004), M Mand (2005-), K Kvinde (2005-)
  • pattype: There are four codes, not six, and three of them changed meaning. Code 1 was Dagpatient until 1986 and Deldoegnspatient from 1987, and then stops entirely at the end of 2001. Code 2 was Natpatient until 1986 and Ambulant from 1987. Code 0 was Heldoegnspatient until 2001 and Indlagt patient from 2002. The register only started using 1, 2 and 3 in 1994, so before that essentially every contact is 0. Code 3 was discontinued at the end of 2013, and from 2014 an emergency-room visit arrives as 2 with an acute admission mode in c_indm. Reading 2 as outpatient across the whole register therefore mislabels night patients before 1987 and emergency visits after 2013.
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • indm: From 2014 this is what separates an emergency-room visit from an ordinary outpatient one, because c_pattype code 3 was discontinued and both arrive as 2. Code 9 (Uoplyst) stops at the end of 2003, so a missing value after that is genuinely missing rather than coded as unknown.
  • c_udm: Only codes 1, 8 and 9 reach back to 1987, and 9 stops in 2003. Discharge to another hospital unit is the trap: it was 3, 5, B or C until 2003 or 2004 and becomes F, G, K or L from 2004 onwards. Counting “discharged onwards to hospital” across the whole register therefore needs both sets, and either set alone gives a series with a hole in it. Codes 2, 4, 7 and A only begin in 1995, E in 2002, and K and L in 2006.
  • c_henm: Only four codes cover the whole register: 0, 1, 2 and 8. Everything else has a window. Codes 3, 5, 9, B, C and D stop at the end of 2003 and 6 stops at the end of 1998, while F and G only begin in 2004, A in 1995 and E in 2002. The end of 2003 is a break: referrals from a hospital unit were coded 3, 5, B, C or D before it and F or G after it. Counting any of those across the whole period gives a number that changes for administrative reasons alone.
  • c_kontaars: Code 4 was Selvtilføjet skade until the end of 1993 and Selvmord/selvmordsforsøg from 1994. Those are not the same population: self-inflicted injury is wider than an attempt at suicide, so a series that spans 1994 changes definition rather than changing level. Codes 5 and 9 stop at the end of 2013. Code 7 only starts in 2011 and code 6 only in 2014, so neither says anything about earlier contacts.
  • sex_lpr: The coding changed at the start of 2005: 1/2 until the end of 2004, M/K from 2005. A study spanning that year that filters on c_sex == "2" keeps only the women seen before 2005 and silently drops the rest, with no error and no empty result to warn you. Take sex from BEF instead, where it is koen coded 1/2 throughout, unless you specifically need what the hospital recorded.

Where these values come from:

Worth knowing:

  • pnr: DST’s variable list calls this column PNR. Some deliveries rename it: some deliveries hand it over as v_cpr. The name is a product of the data processing, not of the register, so check your own columns and rename.
  • recnum: DST’s variable list calls this column RECNUM, the same name the somatic lpr_adm uses. Some deliveries rename it, and not consistently: the contact table can arrive as k_recnum and the diagnosis table as v_recnum. Rename both to recnum before joining.
  • c_pattype: Present here even where the somatic lpr_adm extract leaves it out, so the psychiatric side of a study can be classified when the somatic side cannot. Do not assume symmetry between the two extracts. Until 1993 only patient type 0 (inpatient) was recorded. Day patient (1) was discontinued in 2002, and hospitals then recorded those patients differently (some as outpatients, some as inpatients). Emergency room patient (3) was discontinued in 2014 and replaced by outpatient (2) with acute admission (c_indm = 1).

t_psyk_diag - Psychiatric diagnoses

psyk_diag <- read_register("t_psyk_diag") %>%
  rename_with(tolower) %>%
  rename(recnum = v_recnum)
Column Type Role Label
recnum character join key Contact identifier
c_diag character code Diagnosis code
c_diagtype character code Diagnosis type
c_tildiag character code Supplementary diagnosis
All other columns (2)
Column Type Role Label
leverancedato date date
version character code Version

No published source gives a data type for 2 of these 6 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to T_PSYK_ADM (many-to-one).
Value sets for the coded columns (2)
Code system Values
icd10_sks Not listed here - see DST’s classification
diagtype A Aktionsdiagnose, B Bidiagnose, G Grundmorbus, naar forskellig fra aktionsdiagnose, H Henvisningsdiagnose, M Midlertidig diagnose, kun for aabne somatisk ambulante besoeg, C Komplikation
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • diagtype: The guide long described this as an A/B/G column. There are six codes, and three of them stop: G runs 1995-2003 only, M 1998-2013 and C 2002-2013. A and B run the whole period, H from 1995. So a comorbidity definition built on G silently covers nine years and nothing else, and filtering to A/B/G drops referral diagnoses entirely. Which types to keep is a case definition, not a technicality: outcomes usually use A and B. Carry the type column into the extract so the definition can be varied later.

Where these values come from:

Worth knowing:

  • recnum: DST’s variable list calls this column RECNUM. Some deliveries rename it, and not consistently: this table can arrive as v_recnum while the contact table gets k_recnum. One key, three names. Check and rename to recnum.

4. LPR3 (March 2019 and onwards)

Before you join these two tables: lpr_a_kontakt/lpr_a_diagnose are not pure LPR3. They also hold LPR1, LPR2 and MiniPAS (records from private hospitals) rows, tagged by lprindberetningssystem, going back to around 2017. Filter both tables on lprindberetningssystem == "LPR3" first, or you will double-count contacts already in lpr_adm. See Understand LPR for why, and Extract from LPR for open problems with that filter.

LPR3 covers both somatic and psychiatric contacts in one table. Join: lpr_a_kontakt LEFT JOIN lpr_a_diagnose ON dw_ek_kontakt.

The “a” in lpr_a_diagnose does not mean A-type diagnoses. It refers to the analysis model designation for the LPR3 series (LPR_A, introduced 2025). The table contains all types, A, B and G, so you still need to filter on diag_kode_type.

lpr_a_kontakt - Contacts

Column Type Role Label
dw_ek_kontakt character join key Contact identifier
dw_ek_forloeb character code Course identifier
pnr character identifier Personal identifier
kont_starttidspunkt datetime date Contact start
kont_sluttidspunkt datetime date Contact end
kont_type character code Contact type
lprindberetningssystem character code Reporting system
adiag character code Primary diagnosis
prioritet character code Priority
kont_ans_hovedspec character code Responsible main specialty
year integer date Register year
All other columns (43)
Column Type Role Label
dw_sk_sygehusophold character code Hospital stay identifier
dw_ek_helbredsforloeb character code Health course identifier
dw_ek_borger character code Citizen identifier
adiag_tekst character value Primary diagnosis, text
kont_type_tekst character value Contact type, text
kont_patient_type character code Patient type
kont_patient_type_tekst character value Patient type, text
prioritet_tekst character value Priority, text
kont_aarsag character code Reason for the contact
kont_aarsag_tekst character value Reason for the contact, text
kont_henv_aarsag character code Referral reason
kont_henv_aarsag_tekst character value Referral reason, text
kont_henv_maade character code Referral mode
kont_henv_maade_tekst character value Referral mode, text
kont_henv_instans character code Referring body
kont_henv_tidspunkt datetime date Referral time
kont_indb_tidspunkt datetime date Reporting time
beh_starttidspunkt datetime date Treatment start
flag_kont_afsluttet numeric code Contact closed flag
kont_ans character code Responsible unit
kont_ans_inst character code Responsible institution
kont_ans_hovedspec_shak character code Responsible main specialty, SHAK
kont_ans_geo_reg character code Region of the treating unit, geographic
kont_ans_geo_reg_tekst character value Region of the treating unit, text
kont_ans_org_reg character code Region of the treating unit, organisational
kont_ans_org_reg_tekst character value Organisational region, text
kont_inst_ejertype character code Institution ownership type
kont_fir_kode character code Company code
kont_fir_tekst character value Company, text
kont_fritvalg character code Free choice of hospital
kont_fritvalg_tekst character value Free choice, text
kont_lpr_entity_id character code LPR entity identifier
borger_koen character code Sex
borger_foedselsdato date date Date of birth
borger_doedsdato date date Date of death
borger_alder_aar_ind numeric value Age in years at contact start
borger_alder_aar_ud numeric value Age in years at contact end
borger_bo_kom character code Municipality of residence
borger_bo_kom_tekst character value Municipality of residence, text
borger_bo_reg character code Region of residence
borger_bo_reg_tekst character value Region of residence, text
cprtjek character code CPR check
cprtype character code CPR type
  • dw_sk_sygehusophold: A stay can gather several contacts. Counting rows here is not the same as counting admissions.
  • dw_ek_borger: An internal person key. Use pnr for joins to other registers; this one does not travel outside LPR3.
  • kont_indb_tidspunkt: When the contact was reported, not when it happened. Recent months look incomplete because reporting lags.
  • flag_kont_afsluttet: An open contact has no end time yet, so durations computed near the end of the data are wrong rather than missing.
  • borger_koen: Sex as recorded on the contact, as text rather than a number. No published source gives its value set, so this schema records none. Checked without success: Sundhedsdatastyrelsen’s Vejledning til LPR3_F, which documents these very research tables; the LPR3 reporting guidance; esundhed’s LPR documentation, which covers LPR2 only; and DST’s variable list, which names the column but gives neither label nor values. Treat this as settled rather than as something still to look up. The neighbouring register is no guide either: LPR2’s c_sex switched from 1/2 to M/K in 2005, so both codings exist in the family and neither can be assumed here. If you need sex as a study variable, take koen from BEF, which is documented and stable; if you need what the hospital recorded, check what your own column contains before filtering on it.
  • borger_foedselsdato: A copy from CPR carried on the contact, so it only exists for people who had a hospital contact. BEF is the source to use for a study variable.
  • borger_doedsdato: A death date carried on the contact. It is not a death register: use DOD for mortality, or you only see people who had a hospital contact.

DST publishes no labels for 53 of these columns. Where the Label column is filled in anyway, it is this guide’s reading of the column name, not an official description.

Join key: dw_ek_kontakt.

Joins to other registers:

  • dw_ek_kontakt joins to LPR_A_DIAGNOSE (one-to-many).
Value sets for the coded columns (5)
Code system Values
kont_type Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
icd10_sks Not listed here - see DST’s classification
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
kom Not listed here - see DST’s classification
  • kont_type: ALCA00 means physical attendance, which is the closest LPR3 gets to LPR2’s inpatient flag. It marks attendance, not admission, so a study that treats it as “was admitted” will include outpatient visits. Check what your own delivery holds before filtering: single digits and SKS codes have been seen side by side in the same year, so kont_type == "ALCA00" can silently drop rows that are the same kind of contact recorded in the other form. Cross-tabulate it against lprindberetningssystem first. MiniPAS was the route private providers reported through, so the two forms are not only two notations, they are also two different parts of the health service.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.

Where these values come from:

Worth knowing:

  • dw_ek_kontakt: The key the diagnosis and procedure tables join on.
  • dw_ek_forloeb: One level above the contact: a course of treatment can span several contacts, so joining on this is not the same as joining on the contact.
  • kont_starttidspunkt: A datetime, not a date. as.Date() it before comparing with an index date.
  • lprindberetningssystem: Filter to “LPR3”. The table reaches back to 2017, and the outpatient contacts from before March 2019 are also in LPR2, so combining the two without this filter counts the same contact twice. This is a different thing from LPR_F vs LPR_A: those are two file formats, a choice made before you even open a file, not a value this column can hold. See the lprindberetningssystem code system for the full value set and its confidence levels.
  • adiag: The contact’s action diagnosis, repeated here so simple analyses need not join lpr_a_diagnose. Secondary diagnoses are only in the diagnosis table, so filtering on this column alone misses them.
  • prioritet: The code ATA1 marks an acute contact. Together with the contact’s duration this is how LPR3 substitutes for LPR2’s c_pattype.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.
All confirmed columns in lpr_a_kontakt

pnr, dw_ek_kontakt, kont_starttidspunkt, kont_sluttidspunkt, kont_type, kont_type_tekst, kont_patient_type, kont_patient_type_tekst, kont_ans_hovedspec, kont_ans_hovedspec_shak, kont_ans_inst, kont_ans, kont_ans_geo_reg, kont_ans_geo_reg_tekst, kont_ans_org_reg, kont_ans_org_reg_tekst, borger_doedsdato, borger_foedselsdato, borger_koen, borger_alder_aar_ind, borger_alder_aar_ud, borger_bo_kom, borger_bo_kom_tekst, borger_bo_reg, borger_bo_reg_tekst, dw_sk_sygehusophold, dw_ek_helbredsforloeb, dw_ek_forloeb, dw_ek_borger, adiag, adiag_tekst, beh_starttidspunkt, flag_kont_afsluttet, kont_aarsag, kont_aarsag_tekst, kont_indb_tidspunkt, kont_fir_kode, kont_fir_tekst, kont_fritvalg, kont_fritvalg_tekst, kont_henv_aarsag, kont_henv_aarsag_tekst, kont_henv_instans, kont_henv_maade, kont_henv_maade_tekst, kont_henv_tidspunkt, kont_inst_ejertype, lprindberetningssystem, prioritet, prioritet_tekst, kont_lpr_entity_id, cprtjek, cprtype, year

DST’s variable list: LPR_A_KONTAKT → (in Danish). Look up the specialty code kont_ans_hovedspec in DST’s specialty/department overview → (in Danish).

lpr_a_diagnose - Diagnoses

Column Type Role Label
dw_ek_kontakt character join key Contact identifier
diag_kode character code Diagnosis code
diag_kode_type character code Diagnosis type
senere_afkraeftet character code Later retracted
diag_kode_tekst character value Diagnosis code, text
year integer date Register year
All other columns (6)
Column Type Role Label
diag_parent_kode character code Parent diagnosis code
lprindberetningssystem character code Reporting system
diag_kode_type_tekst character value Diagnosis type, text
diag_parent_kode_tekst character value Parent diagnosis code, text
diag_parent_kode_type character code Parent diagnosis type
diag_parent_kode_type_tekst character value Parent diagnosis type, text
  • lprindberetningssystem: Filter to “LPR3”: the table holds rows from two reporting formats, and not doing so duplicates rows.

DST publishes no labels for 11 of these columns. Where the Label column is filled in anyway, it is this guide’s reading of the column name, not an official description.

Join key: dw_ek_kontakt.

Joins to other registers:

  • dw_ek_kontakt joins to LPR_A_KONTAKT (many-to-one).
Value sets for the coded columns (3)
Code system Values
icd10_sks Not listed here - see DST’s classification
diagtype A Aktionsdiagnose, B Bidiagnose, G Grundmorbus, naar forskellig fra aktionsdiagnose, H Henvisningsdiagnose, M Midlertidig diagnose, kun for aabne somatisk ambulante besoeg, C Komplikation
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • icd10_sks: The D prefix is a Danish addition, not part of the WHO code. Matching WHO codes directly against LPR without allowing for it returns nothing. Do not carry the habit across to the cause-of-death registers: they hold the plain code, so stripping a D there removes the first real character instead.
  • diagtype: The guide long described this as an A/B/G column. There are six codes, and three of them stop: G runs 1995-2003 only, M 1998-2013 and C 2002-2013. A and B run the whole period, H from 1995. So a comorbidity definition built on G silently covers nine years and nothing else, and filtering to A/B/G drops referral diagnoses entirely. Which types to keep is a case definition, not a technicality: outcomes usually use A and B. Carry the type column into the extract so the definition can be varied later.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Worth knowing:

  • senere_afkraeftet: A diagnosis that was subsequently withdrawn. Keeping these counts conditions the patient turned out not to have.
  • diag_kode_tekst: The code spelled out. Convenient for reading, but do not group on it: the text can change between years while the code stays the same.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

Standard filter for senere_afkraeftet:

filter(is.na(senere_afkraeftet) | senere_afkraeftet != "Ja")

5. LPR - SKS procedure codes

SKS (Sundhedsvæsenets Klassifikations System - the Danish Health Classification System) is the Danish classification system for operations and procedures - equivalent to the NOMESCO codes used in the other Nordic countries. Bariatric surgery has e.g. codes KJDF10 (RYGB) and KJDF40 (sleeve gastrectomy). Look up codes in the SKS browser → (in Danish).

SKS codes are split across two registers depending on period. For full coverage both must be queried and the results bound together.

Neither procedure table holds pnr. It is fetched by joining to lpr_adm (LPR2) or lpr_a_kontakt (LPR3).

lpr_sksopr - LPR2 SKS procedures (up to 2018)

Location (DARTER): parquet-registers/lpr_sksopr

lpr_sksopr <- read_register("lpr_sksopr") %>%
  rename_with(tolower)
Column Type Role Label
recnum character join key Contact identifier
c_opr character code Procedure code
c_oprart character code Procedure type
c_osgh character code Hospital performing the procedure
c_tilopr character code Supplementary code
d_odto date date Procedure date
year integer date Register year
All other columns (5)
Column Type Role Label
c_oafd character code Procedurende afdeling (operation)
leverancedato date date
version character code Version
v_ominut numeric value Procedureminut (operation)
v_otime numeric value Proceduretime (operation)

No published source gives a data type for 8 of these 12 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to LPR_ADM (many-to-one).
Value sets for the coded columns (2)
Code system Values
sks Not listed here - see DST’s classification
oprart V Vigtigste operation i afsluttet kontakt, P Vigtigste operation i operativt indgreb, D Deloperation, + Tillaegskode
  • sks: The codes are hierarchical, so a prefix match selects a whole branch. That also makes it easy to select more than you meant: check how many characters your intended group actually needs before filtering with starts_with().
  • oprart: Counting rows in the procedure table counts add-on codes and sub-procedures as procedures. If you want one row per operation, filter to V or P first. All four codes run from 1996 with no breaks.

Where these values come from:

Worth knowing:

  • c_opr: The SKS procedure code. Surgical codes start with K.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

lpr_a_procregistrering - LPR3 SKS procedures (2019 and onwards)

The LPR3 procedure table. It sits alongside lpr_a_kontakt and lpr_a_diagnose, and joins to contacts on dw_ek_kontakt exactly like the diagnosis table does. Column names confirmed against DST’s variable list →.

Column Type Role Label
dw_ek_kontakt character join key Contact identifier
proc_kode character code Procedure code
proc_starttidspunkt datetime date Procedure start
proc_kode_type character code Procedure code type
proc_sluttidspunkt datetime date Procedure end
proc_parent_kode character code Parent procedure code
dw_ek_forloeb character code Course identifier
flag_proc_uden_kont character code Procedure without a contact
lprindberetningssystem character code Reporting system
All other columns (11)
Column Type Role Label
dw_ek_procedureregistrering character identifier Procedure registration identifier
dw_sk_sygehusophold character code Hospital stay identifier
proc_indb_tidspunkt datetime date Reporting time
proc_kode_tekst character value Procedure code, text
proc_kode_type_tekst character value Procedure code type, text
proc_parent_kode_tekst character value Parent procedure code, text
proc_parent_kode_type character code Parent procedure code type
proc_parent_kode_type_tekst character value Parent procedure code type, text
proc_lpr_entity_id character code LPR entity identifier
prod_enh character code Performing unit
prod_inst character code Performing institution
  • proc_indb_tidspunkt: When the procedure was reported, not when it happened. Recent months look incomplete because reporting lags.

DST publishes no labels for 20 of these columns. Where the Label column is filled in anyway, it is this guide’s reading of the column name, not an official description.

No published source gives a data type for 20 of these 20 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: dw_ek_kontakt.

Joins to other registers:

  • dw_ek_kontakt joins to LPR_A_KONTAKT (many-to-one).
Value sets for the coded columns (2)
Code system Values
sks Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • sks: The codes are hierarchical, so a prefix match selects a whole branch. That also makes it easy to select more than you meant: check how many characters your intended group actually needs before filtering with starts_with().
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Worth knowing:

  • dw_ek_kontakt: The key to lpr_a_kontakt, which is where pnr lives. This table carries no person identifier of its own.
  • proc_starttidspunkt: A datetime, not a date. as.Date() it before comparing with an index date.
  • proc_kode_type: “P” marks a procedure, “+” an add-on code. An add-on code modifies the procedure above it and is not a procedure in its own right, so counting all rows overcounts.
  • proc_parent_kode: LPR3 nests procedures the same way it nests diagnoses: an add-on code points at the procedure it belongs to.
  • dw_ek_forloeb: One level above the contact. Where dw_ek_kontakt is empty, this is the only route back to a person, and it reaches a whole course of treatment rather than a single contact.
  • flag_proc_uden_kont: Flags a procedure with no contact attached. Those rows cannot be joined to lpr_a_kontakt at all, so a plain inner join drops them silently.
  • lprindberetningssystem: Filter to “LPR3” when combining with LPR2, or contacts reported under both systems are counted twice.

There is no pnr here, as in every LPR procedure table: it identifies procedures, not people. Join to lpr_a_kontakt to get one.

A few rows have no contact to join to, and DST flags them for you in flag_proc_uden_kont. Count them before you drop them.

library(fastreg) # read_register()
library(dplyr) # filter, select, inner_join, mutate, collect

proc <- read_register("lpr_a_procregistrering") %>%
  rename_with(tolower) %>%
  filter(lprindberetningssystem == "LPR3") %>% # same duplicate filter as the contacts
  filter(proc_kode %in% !!MY_CODES) %>% # your SKS codes
  select(dw_ek_kontakt, proc_starttidspunkt)

surgery <- read_register("lpr_a_kontakt") %>%
  rename_with(tolower) %>%
  filter(lprindberetningssystem == "LPR3") %>%
  select(dw_ek_kontakt, pnr) %>% # pnr lives here
  inner_join(proc, by = "dw_ek_kontakt") %>%
  mutate(date_procedure = as.Date(proc_starttidspunkt)) %>%
  select(pnr, date_procedure) %>%
  collect()

lpr_sksube - SKS examinations and treatments (ZZ codes)

Examination and treatment codes (ZZ codes) live in lpr_sksube (LPR2), separate from the operation codes in lpr_sksopr above. Join like the other SKS tables, via recnum. The register is shaped exactly like lpr_sksopr.

Column Type Role Label
recnum character join key Contact identifier
c_opr character code Procedure code
d_odto date date Procedure date
year integer date Register year
All other columns (8)
Column Type Role Label
c_oprart character code Procedure type
c_osgh character code Hospital performing the procedure
c_tilopr character code Supplementary code
c_oafd character code Procedurende afdeling (undersøgelse & behandling)
leverancedato date date
version character code Version
v_ominut numeric value Procedureminut (undersøgelse & behandling)
v_otime numeric value Proceduretime (undersøgelse & behandling)

No published source gives a data type for 8 of these 12 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: recnum.

Joins to other registers:

  • recnum joins to LPR_ADM (many-to-one).
Value sets for the coded columns (2)
Code system Values
sks Not listed here - see DST’s classification
oprart V Vigtigste operation i afsluttet kontakt, P Vigtigste operation i operativt indgreb, D Deloperation, + Tillaegskode
  • sks: The codes are hierarchical, so a prefix match selects a whole branch. That also makes it easy to select more than you meant: check how many characters your intended group actually needs before filtering with starts_with().
  • oprart: Counting rows in the procedure table counts add-on codes and sub-procedures as procedures. If you want one row per operation, filter to V or P first. All four codes run from 1996 with no breaks.

Where these values come from:

Worth knowing:

  • c_opr: Check that you actually have this column. DST documents it for every year 1999-2019, but a delivery can arrive with only recnum, d_odto and year, which leaves no way to tell one procedure from another. Without it the table is unusable, and no filtering recovers it.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

Check that you actually have c_opr before planning around this register. DST documents it for every year 1999-2019, but at least one delivery contains only recnum, d_odto and year, which cannot tell one procedure from another. Run colnames() first.

Combination across the full period

See the code example: combination across the full period
# Replace [projectnumber] with your own project number
# With fastreg: read_register("registername") instead of open_dataset("path/to/registername/")

# SKS from LPR2 (up to 2018)
surg_lpr2 <- read_register("lpr_sksopr") %>%
  rename_with(tolower) %>%
  filter(toupper(c_opr) %in% !!SKS_CODES) %>%   # !! sends the local R vector to DuckDB
  left_join(
    read_register("lpr_adm") %>%
      rename_with(tolower) %>%
      select(recnum, pnr, d_inddto),
    by = "recnum"
  ) %>%
  select(pnr, surgery_date = d_odto, surgery_code = c_opr) %>%
  collect()

# SKS from LPR3 (2019 and onwards) - join via dw_ek_kontakt
surg_lpr3 <- read_register("lpr_a_procregistrering") %>%
  rename_with(tolower) %>%
  filter(toupper(proc_kode) %in% !!SKS_CODES) %>%   # !! sends the local R vector to DuckDB
  left_join(
    read_register("lpr_a_kontakt") %>%
      rename_with(tolower) %>%
      select(dw_ek_kontakt, pnr),
    by = "dw_ek_kontakt"
  ) %>%
  mutate(surgery_date = as.Date(proc_starttidspunkt)) %>%
  select(pnr, surgery_date, surgery_code = proc_kode) %>%
  collect()

# Combined
surg_all <- bind_rows(surg_lpr2, surg_lpr3)

6. Other clinical registers

These registers are used less often than those above and are not column-verified here - the descriptions give an overview, but look up the exact variable names in DST’s overview of registers and variable lists and confirm against your own files with colnames().

MFR - Medical Birth Register

One row per birth, carrying both mother and child. The mother appears once per birth, so a mother of three has three rows; the register is keyed on the child through cpr_barn.

Three eras, three different data models, not one register with minor revisions. 1973-1996 was paper form reports; not an “MFR” table, but not undocumented either - DST’s own ftbarn/ftforael/ftnaevn (“Fertilitet - børn/forælder/Nævner”) datasets cover 1973-2023 and explicitly incorporate MFR content (ftbarn’s weight/length columns are documented as matching MFR, alongside its own MFR_OPLYSNING column). These are demography datasets (parity, birth spacing, fertility-rate denominators), not a clinical birth-event table - see below. 1997-2018 is the wide DST table below (mfr), marked closed by DST with no successor named on DST’s own overview - because the successor is delivered by Sundhedsdatastyrelsen’s Forskerservice, not DST, the same pattern as lpr_a_kontakt. Nineteen of mfr’s own columns are flags backed by their own separate DST datasets, plus a full stillbirth detail table - see MFR marker sub-cuts and MFRDFOED below. From 2019 onwards the register was fully restructured into a main table (Nyfoedte) plus ten LPR3-style satellite tables per mother and child (Barn_Forloeb/Kontakter/Diagnoser/Procedurer/Resultater and the same five Mor_* tables) - see mfr_nyfoedte below. This replaces an earlier, incorrect version of this page’s guidance, which guessed the split was simply MFR_MOR_*/MFR_BARN_* tables.

The 2019+ population also differs from the two older eras: 1973-2018 required the mother to have a Danish CPR-number, 2019+ does not. A study spanning this boundary is comparing two different populations, not only two table shapes.

FTBARN / FTFORAEL / FTNAEVN - the pre-1997 period

Three separate DST datasets, not one register split three ways: ftbarn (one row per child), ftforael (one row per parent-child link, up to two per child), and ftnaevn (one row per person per year - the fertility-rate denominator, not a birth-event table at all). All three cover 1973-2023, so they overlap with mfr and mfr_nyfoedte in time; use them for the years those two do not reach, 1973-1996.

DST’s own variable-list pages for these three give a short Danish label for some columns and none at all for others - no value/code definitions anywhere. Unlike mfr_nyfoedte, there is no code_system on any coded column here (KOEN, LEVENDE_ELLER_DOEDFOEDT, CPRTYPE, MOR_FAR, and more): inventing a lookup neither DST nor any other source confirms would be actively misleading. Confirm actual values with count()/table() on real data before writing code that filters or recodes on any of them.

ftforael’s four parity/spacing variants (DEMOGRAFISK_/ENKELT_/FAMILIE_/MEDICINSK_PARITET, and the matching _SPACING columns) are not further defined by DST relative to each other or to the simpler PARITET column - see ftforael.yaml’s reader_note before picking one for an analysis.

Column Type Role Label
PNR character join key Personal identifier
FOED_DAG date date Date of birth
LEVENDE_ELLER_DOEDFOEDT character code Live birth or stillbirth
All other columns (31)
Column Type Role Label
FOEDAAR numeric value Year of birth
KOEN character code Sex
FLERFOLD character code Multiple birth (single, twin, triplet, quadruplet)
VAEGT_BARN numeric value Birth weight in grams (from MFR)
LAENGDE_BARN numeric value Birth length in cm (from MFR)
MFR_OPLYSNING character code Child found in the Medical Birth Register (MFR)
FOEDREG_DK character code Birth registered with a Danish authority code
FOEDREG_KODE character code Birth registration authority code
FOEDTE_POPULATION character code Population boundary relative to DST’s births statistics
INDDAG numeric value Child’s age in days at first CPR registration
CPRTJEK character code CPR check
CPRTYPE character code CPR type
MOR1 character code Earliest registered mother
MOR2 character code Latest mother, if different from mor1
MOR_ALDER numeric value Mother’s age
MOR_ALDER_ULT numeric value Mother’s age at the end of the year
MOR_FOED_ADOP character code Mother’s relation to the child (adoptive or other non-biological)
MOR_KOEN character code Mother’s (mor1) sex
MOR_VFRA character value Date the current mother became the parent
M_KILDE character code Source of the mor1 information
FAR1 character code Earliest registered father/co-mother
FAR2 character code Latest father/co-mother, if different from far1
FAR_ALDER numeric value Father’s (far1) age on the child’s birthday
FAR_ALDER_ULT numeric value Father’s (far1) age at the end of the birth year
FAR_FOED_ADOP character code Father’s relation to the child (adoptive or other non-biological)
FAR_KOEN character code Father’s (far1) sex
FAR_VFRA character value Date the current father/co-mother became the parent
F_KILDE character code Source of the far1 information
B_KILDE character code Source of the child’s data
MDOED character code Death marker (stillborn, died in first year, survived first year, died later)
VERSION character value Module data version
  • KOEN: Not confirmed against either koen (DST’s numeric 1/2/9) or mfr_koen (SDS’s letter K/M/Ukendt): DST’s page for this register gives no value definitions at all, so which encoding this register actually uses is unverified. Check with table() on real data before assuming either.
  • FLERFOLD: Multiple-birth indicator, by the variable name - not confirmed by any DST description text.
  • VAEGT_BARN: -1 likely means not stated, matching mfr_nyfoedte’s own Vaegt_Barn convention, per DST’s October 2025 change note - not independently confirmed on this register’s own variable-list page.
  • MFR_OPLYSNING: The explicit link to the Medical Birth Register: this column is Sundhedsdatastyrelsen’s own confirmation that FTBARN draws medical birth detail from MFR, not DST inventing an equivalent independently. Exact meaning of its values is not documented on DST’s page.
  • CPRTJEK: Likely a CPR-number validity check, by name analogy to mfr_er_cprnummer_gyldigt - not confirmed to share that code system’s values, since DST’s page for this register defines neither.
  • MOR1: The earliest mother registered for this child. MOR1 and MOR2 can differ: CRS parental links are sometimes corrected or reassigned after the fact (e.g. following a legal dispute or a data error), and this register keeps both the original and the current answer rather than silently overwriting one with the other.
  • MOR2: The current/most recently registered mother. See MOR1’s reader_note.
  • MOR_FOED_ADOP: Biological vs adoptive, by the variable name (FOED = født = born, ADOP = adopteret) - not itself confirmed by DST’s description text.
  • FAR1: The earliest father registered for this child. See MOR1’s reader_note - same pattern, paternal side.

No published source gives a data type for 33 of these 34 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: PNR.

Joins to other registers:

  • PNR joins to BEF (many-to-one).

Worth knowing:

  • PNR: The child’s own personnummer.
  • LEVENDE_ELLER_DOEDFOEDT: Value codes not given by DST’s page - see the register-level note on unconfirmed code values.
Column Type Role Label
PNR character join key Personal identifier
FORAELDER_PNR character join key Parent’s personal identifier
MOR_FAR character code Whether the parent is the mother or the father
All other columns (17)
Column Type Role Label
FOED_DAG date date Date of birth
DOED_DATO date date Child’s date of death
MDOED character code Death marker (stillborn, died in first year, survived first year, died later)
FLERFOLD character code Multiple birth (single, twin, triplet, quadruplet)
ADOP character code Adoptive or other non-biological relation to the child
PARITET numeric value Mother’s delivery number as recorded in MFR
DEMOGRAFISK_PARITET numeric value Child’s birth order among live-born siblings
ENKELT_PARITET numeric value Child’s order among singleton-born siblings
FAMILIE_PARITET numeric value Child’s order among siblings who survived their first year
MEDICINSK_PARITET numeric value Mother’s delivery number (stillbirths count, a multiple birth counts once)
DEMOGRAFISK_SPACING numeric value Days to the next live-born sibling
ENKELT_SPACING numeric value Days to the next singleton-born sibling
FAMILIE_SPACING numeric value Days to the next sibling, both surviving their first year
MEDICINSK_SPACING numeric value Days to the mother’s next delivery
CPRTJEK character code CPR check
CPRTYPE character code CPR type
VERSION character value Module data version
  • FOED_DAG: The child’s birth date, not the parent’s.
  • ADOP: Adoption indicator, by the variable name - not confirmed by any DST description text, and no code values given.
  • PARITET: A simple sequential birth number for the mother (labelled specifically as “moderens fødsel nummer”), distinct from the four PARITET/SPACING variant columns below, which DST does not further define relative to this one or to each other.

No published source gives a data type for 20 of these 20 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: PNR.

Joins to other registers:

  • PNR joins to FTBARN (many-to-one).
  • FORAELDER_PNR joins to BEF (many-to-one).

Worth knowing:

  • PNR: The child’s own personnummer, joining back to ftbarn.PNR - not the parent’s.
  • FORAELDER_PNR: The parent’s personnummer, joining to bef.pnr. Which parent (mother or father) is given by MOR_FAR.
  • MOR_FAR: Value codes not given by DST’s page (likely something like Mor/Far, not confirmed). Group by PNR and count rows before assuming every child has exactly two: a child with an unknown or unregistered parent has only one row here, for the parent that is known.
Column Type Role Label
PNR character join key Personal identifier
AAR numeric date Register or census year
All other columns (13)
Column Type Role Label
FOED_DAG date date Date of birth
KOEN character code Sex
ALDER_START numeric value Age at the start of the year
ALDER_SLUT numeric value Age at the end of the year
ANDEL numeric value Share of the fertile age interval lived in the population (percent)
ANTAL_BOERN_START numeric value Number of children (as mor1/far1) at the start of the year
ANTAL_BOERN_SLUT numeric value Number of children (as mor1/far1) at the end of the year
ANTAL_DAGE_START numeric value Days in the population at the start-of-year age
ANTAL_DAGE_SLUT numeric value Days in the population at the end-of-year age
PRIMO_ULTIMO character code In the population at the start, end or both of the year
CPRTJEK character code CPR check
CPRTYPE character code CPR type
VERSION character value Module data version
  • KOEN: Not confirmed against either koen (DST’s numeric 1/2/9) or mfr_koen (SDS’s letter K/M/Ukendt) - see ftbarn.yaml’s own KOEN column for the same unresolved question.
  • ALDER_START: Age at the start of the reference year, by the variable name.
  • ALDER_SLUT: Age at the end of the reference year, by the variable name.
  • ANDEL: The proportion of the year this person spent within the fertile age range - the core denominator quantity this register exists to supply. Exact age bounds for “fertile age” are not given on DST’s variable-list page.
  • ANTAL_BOERN_START: Number of children at the start of the reference year, by the variable name.
  • ANTAL_BOERN_SLUT: Number of children at the end of the reference year, by the variable name.
  • PRIMO_ULTIMO: “Primo” (start of period) vs “ultimo” (end of period), by the variable name - plausibly an indicator of which of the _START/_SLUT column pairs above a given row’s other values line up with, but this is read from the name alone, not confirmed by any DST description text.

No published source gives a data type for 15 of these 15 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: PNR, AAR.

Joins to other registers:

  • PNR joins to BEF (many-to-one).

Worth knowing:

  • AAR: Together with PNR this is the row’s key: one row per person per year.

gestationsalder_dage is in days, not weeks. paritet counts previous births, which is not the same as the number of children currently alive.

Column Type Role Label Years
alder_moder numeric value Mother’s age
bmi_moder numeric value Mother’s BMI 2003 to 2018
cpr_barn character join key Child’s CPR number
cpr_moder character join key Mother’s CPR number
flerfoldsfoedsel_beregnet character code Child’s order in a multiple birth (derived)
gestationsalder_dage numeric value Gestational age in days
hoejde_moder numeric value Mother’s height (cm) 2003 to 2018
laengde_barn character code Child’s length (cm)
paritet numeric value Parity: completed pregnancies including stillbirths, counting this birth
rygerstatus_moder character code Mother’s smoking status (DUT codes)
vaegt_barn numeric value Child’s weight (grams)
vaegt_moder numeric value Mother’s weight 2003 to 2018
All other columns (79)
Column Type Role Label Years
abdominalomfang numeric value Child’s abdominal circumference (cm)
abruptio character code Placental abruption (ICD-10 code)
afdeling character code Hospital department
alderveddoed_dage_barn numeric value Child’s age at death (days)
alder_fader numeric value Father’s age
amnioinfusion character code Amnioinfusion during birth (SKS procedure code) 1998 to 2018
amnitomi_under_foedsel_hsp character code Amniotomy (SKS procedure code, or 1 = performed)
andensutur character code Other suture after birth (SKS procedure code)
apgarscore_efter5minutter numeric value Apgar score at 5 minutes (0-10, 99 = unknown)
barnslevendenr_flerfoldfoedsel numeric value Live-born number in a multiple birth
barnsnummer_flerfoldsfoedsel numeric value Number in a multiple birth
besoeghosjordemoder character code Number of midwife visits during pregnancy
besoeghoslaege character code Number of GP visits during pregnancy
besoeghosspeciallaege character code Number of specialist visits during pregnancy
bopaelskommune_moder character code Mother’s municipality of residence
cpapbeh_neonatalafdeling character code Admitted to neonatal unit and given CPAP (SKS treatment code) 2000 to 2018
cpr_fader character join key Father’s CPR number
disproportio character code Disproportion (obstructed labour from abnormal pelvis, ICD-10 code)
doedsdato_barn date date Child’s date of death
doedsdato_moder date date Mother’s date of death
epiduralblokade character code Epidural block (SKS treatment or anaesthesia code) 2000 to 2018
episiotomi character code Episiotomy (SKS procedure code, or 1 = performed)
fastsiddendemoderkage character code Retained placenta and membranes without bleeding (ICD-10 code)
flerfoldsgraviditet character code Multiple pregnancy diagnosis (ICD-10 code)
foedested character code Place of birth (SKS code)
foedselsaar character code Year of birth
foedselsdato date date Child’s date of birth
foedselsdiagnose_moder character code Mother’s birth diagnosis
foedselsloebenummer numeric value Birth serial number
foedselstime character code Hour of birth
fosterpraesentation character code Fetal presentation (DUP codes)
hjemmebesoeg character code Home visit 2003 to 2018
hovedomfang numeric value Child’s head circumference
intrauterin_asfyxi character code Intrauterine asphyxia, threatened fetal hypoxia (SKS diagnosis code)
intrauterin_palpation character code Manual exploration of the uterus after birth (SKS procedure code)
kejsersnit_modersoenske character code Caesarean section at the mother’s request 2002 to 2018
koen_barn character code Child’s sex
levende_eller_doedfoedt character code Live birth or stillbirth
markoer_accreta character code Marker: Placenta accreta
markoer_anaestesi_til_operation character code Marker: Anaesthesia for surgery 2000 to 2018
markoer_andre_foedselskomplikati character code Marker: Other birth complications
markoer_b_misdannelse character code Marker: Malformation in the child
markoer_cardiomyopati character code Marker: Cardiomyopathy
markoer_graviditetskomplikatio character code Marker: Pregnancy complications
markoer_haemoperitoneum character code Marker: Haemoperitoneum
markoer_hjemmefoedsel_beregnet character code Marker: Home birth (derived)
markoer_igangsaettelse character code Marker: Induction of labour
markoer_infektioner character code Marker: Infections
markoer_kejsersnit character code Marker: Caesarean section
markoer_medicinske_sygdomme character code Marker: Medical conditions
markoer_navlesnorsblod_analyse character code Marker: Umbilical cord blood analysis 2003 to 2018
markoer_perineal_bristning character code Marker: Perineal tear
markoer_post_partum_bloedning character code Marker: Postpartum haemorrhage
markoer_ruptur character code Marker: Uterine rupture
markoer_smertelindring character code Marker: Pain relief 1999 to 2018
markoer_ultralyd character code Marker: Ultrasound 1999 to 2018
markoer_vestimulation character code Marker: Labour stimulation 1999 to 2018
markoer_ydre_vending character code Marker: External cephalic version
navlesnorsfremfald character code Umbilical cord prolapse (SKS diagnosis code)
pk_mfr character code Primary key, joins to fk_mfr in the satellite tables
placentavaegt numeric value Placental weight (grams)
polyhydramnios character code Polyhydramnios (SKS diagnosis code)
pprom character code Preterm prelabour rupture of membranes (ICD-10 code)
praevia character code Placenta praevia (ICD-10 code)
prom character code Prelabour rupture of membranes (ICD-10 code)
respiratorbeh_neonatalafdeling character code Admitted to neonatal unit and given ventilator treatment (1 = yes) 2000 to 2018
sengedage_beregnet_barn numeric value Child’s bed days for the birth admission (derived)
sengedage_beregnet_moder numeric value Mother’s bed days for the birth admission (derived)
sengedage_neonatalafdeling_barn numeric value Bed days in a neonatal unit, if transferred
sepsis_barn character code Sepsis in the child (ICD-10 code)
skalp_blodproeve character code Fetal scalp blood sampling, scalp pH (SKS treatment code) 2000 to 2018
suturcollum character code Suture of the cervix after birth (SKS procedure code)
sygehus character code Hospital code
tang_forloesning character code Forceps delivery (SKS procedure code)
tegn_paa_asphyxi character code Signs of asphyxia (ICD-10 code)
tidligerefoedsler_i_danmark character code Number of previous births in Denmark
tidligerekejsersnit_i_danmark character code Number of previous caesarean sections in Denmark
tidligerespontaneaborter character code Number of previous spontaneous abortions
vakuumekstraktion character code Vacuum extraction (SKS procedure code)
  • cpapbeh_neonatalafdeling: DST’s variable list gives this column from 2000, but Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives it as valid from 2001. Check the first years in your own data before relying on them.
  • levende_eller_doedfoedt: Stillbirths flagged here have their own richer detail table, mfrdfoed (see mfrdfoed.yaml), joined via FK_MFR - not confirmed one-to-one, but every stillbirth row here is expected to have a match there.
  • markoer_accreta: A flag only - the actual SKS-coded placenta accreta finding is in a separate dataset, mfraccre (see mfraccre.yaml), joined via FK_MFR.
  • markoer_anaestesi_til_operation: A flag only - the actual SKS-coded anaesthesia for an operation finding is in a separate dataset, mfranaes (see mfranaes.yaml), joined via FK_MFR.
  • markoer_andre_foedselskomplikati: A flag only - the actual SKS-coded other birth complications not covered by the more specific sub-cuts finding is in a separate dataset, mfrakmpl (see mfrakmpl.yaml), joined via FK_MFR.
  • markoer_b_misdannelse: A flag only - the actual SKS-coded congenital malformation finding is in a separate dataset, mfrmisda (see mfrmisda.yaml), joined via FK_MFR.
  • markoer_cardiomyopati: A flag only - the actual SKS-coded cardiomyopathy finding is in a separate dataset, mfrcardi (see mfrcardi.yaml), joined via FK_MFR.
  • markoer_graviditetskomplikatio: A flag only - the actual SKS-coded pregnancy complications finding is in a separate dataset, mfrgkmpl (see mfrgkmpl.yaml), joined via FK_MFR.
  • markoer_haemoperitoneum: A flag only - the actual SKS-coded haemoperitoneum finding is in a separate dataset, mfrhaemo (see mfrhaemo.yaml), joined via FK_MFR.
  • markoer_hjemmefoedsel_beregnet: A flag only - the actual SKS-coded home births finding is in a separate dataset, mfrhjmfo (see mfrhjmfo.yaml), joined via FK_MFR. DST’s variable list gives this column from 1997, but Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives it as valid from 2000. Check the first years in your own data before relying on them.
  • markoer_igangsaettelse: A flag only - the actual SKS-coded labour induction finding is in a separate dataset, mfrigang (see mfrigang.yaml), joined via FK_MFR.
  • markoer_infektioner: A flag only - the actual SKS-coded infections finding is in a separate dataset, mfrinfek (see mfrinfek.yaml), joined via FK_MFR.
  • markoer_kejsersnit: A flag only - the actual SKS-coded caesarean section finding is in a separate dataset, mfrkjsnt (see mfrkjsnt.yaml), joined via FK_MFR.
  • markoer_medicinske_sygdomme: A flag only - the actual SKS-coded medical conditions finding is in a separate dataset, mfrmedsg (see mfrmedsg.yaml), joined via FK_MFR.
  • markoer_navlesnorsblod_analyse: A flag only - the actual SKS-coded umbilical cord blood analysis, with the actual pH/base excess values finding is in a separate dataset, mfrnvlan (see mfrnvlan.yaml), joined via FK_MFR. Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives this as valid from 1998, while DST’s variable list starts it in 2003, so DST may not deliver the years 1998-2002.
  • markoer_perineal_bristning: A flag only - the actual SKS-coded perineal tears finding is in a separate dataset, mfrbrist (see mfrbrist.yaml), joined via FK_MFR.
  • markoer_post_partum_bloedning: A flag only - the actual SKS-coded postpartum blood loss, with the actual measured amount finding is in a separate dataset, mfrblodm (see mfrblodm.yaml), joined via FK_MFR. DST’s variable list gives this column from 1997, but Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives it as valid from 2009. Check the first years in your own data before relying on them. The gap is twelve years, so a postpartum haemorrhage series built on this flag before 2009 is unlikely to mean what it means from 2009.
  • markoer_ruptur: A flag only - the actual SKS-coded rupture finding is in a separate dataset, mfrruptu (see mfrruptu.yaml), joined via FK_MFR.
  • markoer_smertelindring: A flag only - the actual SKS-coded pain relief finding is in a separate dataset, mfrsmlin (see mfrsmlin.yaml), joined via FK_MFR.
  • markoer_ultralyd: A flag only - the actual SKS-coded ultrasound finding is in a separate dataset, mfrultra (see mfrultra.yaml), joined via FK_MFR.
  • markoer_vestimulation: A flag only - the actual SKS-coded labour stimulation finding is in a separate dataset, mfrvestm (see mfrvestm.yaml), joined via FK_MFR.
  • markoer_ydre_vending: A flag only - the actual SKS-coded external cephalic version finding is in a separate dataset, mfryvend (see mfryvend.yaml), joined via FK_MFR.
  • respiratorbeh_neonatalafdeling: DST’s variable list gives this column from 2000, but Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives it as valid from 2001. Check the first years in your own data before relying on them.
  • skalp_blodproeve: Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives this as valid from 1997, while DST’s variable list starts it in 2000, so DST may not deliver the years 1997-1999.
  • tidligerefoedsler_i_danmark: In Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) the descriptions of this column and tidligerekejsersnit_i_danmark are swapped (this one is described as previous caesarean sections). The labels here follow the column names. Check which is which in your data: previous caesareans cannot outnumber previous births.
  • tidligerekejsersnit_i_danmark: In Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) the descriptions of this column and tidligerefoedsler_i_danmark are swapped (this one is described as previous births). The labels here follow the column names. Check which is which in your data: previous caesareans cannot outnumber previous births.

No published source gives a data type for 91 of these 91 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: cpr_barn.

Joins to other registers:

  • pnr joins to BEF (many-to-one).

Worth knowing:

  • bmi_moder: Only from 2003, unlike most of the register, which starts in 1997.
  • cpr_barn: The child’s CPR number, which is how the register joins to every other register about the child.
  • cpr_moder: The mother’s CPR number. There is a row per child, so a mother of three appears three times.
  • gestationsalder_dage: Gestational age in days, not weeks. Divide by 7 for the usual clinical scale.
  • paritet: Parity. Counts previous births, so it is not the same as the number of children currently alive.
  • vaegt_moder: Sundhedsdatastyrelsen’s documentation of the birth register for 1997-2018 (Dokumentation_Foedselsregisteret_1997_2018.xlsx) gives the unit as grams, but for an adult’s weight that may be an error in the documentation; check the range in your data before converting.

MFRHJMFO - home births, 1997-2018

Supplementary clinical detail for the home-birth subset of mfr, joined via FK_MFR - not a separate population: mfr already includes home births, flagged via its own FOEDESTED and MARKOER_HJEMMEFOEDSEL_BEREGNET columns. This is the DST-native counterpart to a data-management convention of splitting the 1997-2018 era into “home” and “not-home” deliveries.

DST’s page gives no Danish label at all for any column here, not even the partial labelling ftbarn/ftforael/ftnaevn have - the thinnest documentation of any register in this schema. Every reader_note on this register’s columns is an informed guess from the variable name alone (Danish administrative/clinical vocabulary), not a sourced fact.

Column Type Role Label
FK_MFR character join key
All other columns (31)
Column Type Role Label Years
CPR_MODER character join key
FOEDSELSDATO date date
FOEDSELSKLOKKESLAET character value
KOEN_BARN character code
LEVENDE_ELLER_DOEDFOEDT character code
ENKELT_ELLER_FLERFOLDSFOEDSEL character code
BARNSNUMMER_FLERFOLDSFOEDSEL numeric value 1997 to 2008
GESTATIONSALDER_UGER numeric value
GESTATIONSALDER_DAGE_EFTER_UGER numeric value
TERMINSDATO date date
PARITET numeric value
NORMAL_GRAVIDITET character code 2002 to 2018
RISIKOFAKTORER character value
RYGERSTATUS_MODER character code
VAEGT_BARN numeric value
LAENGDE_BARN numeric value
HOVEDOMFANG numeric value
ABDOMINALOMFANG numeric value
PLACENTAVAEGT numeric value
APGARSCORE_EFTER5MINUTTER numeric value
TEGN_PAA_ASPHXI character code
FOSTERPRAESENTATION character code
MISDANNELSER character code
AMNITOMI_UNDER_FOEDSEL_HSP character code AMNITOMI_UNDER_FOEDSEL_HSP
EPISIOTOMI character code
FOEDSELSKODER character code
BESOEGHOSJORDEMODER character value
BESOEGHOSLAEGE character value
BESOEGHOSSPECIALLAEGE character value
INSTITUTION_INTERN character code
TIMES numeric value
  • KOEN_BARN: Value codes not given by DST’s page - not confirmed to share koen or mfr_koen’s encoding.
  • BARNSNUMMER_FLERFOLDSFOEDSEL: Not continuously available across its own 1997-2008 window: check per-year before assuming this column exists for a given year.
  • GESTATIONSALDER_DAGE_EFTER_UGER: The remainder days beyond GESTATIONSALDER_UGER’s whole weeks, by the variable name.
  • TERMINSDATO: Estimated due date, by the variable name. Not available for year 2000 specifically.
  • RISIKOFAKTORER: Not available for year 2003 specifically.
  • RYGERSTATUS_MODER: The mother’s smoking status for home births specifically. Not confirmed to share tobaksforbrug’s DUT/RGAB SKS coding: this register predates the 2019+ restructuring entirely and DST’s page gives no value definitions to check against.
  • TEGN_PAA_ASPHXI: Signs of asphyxia (birth asphyxia), by the variable name.
  • FOSTERPRAESENTATION: Fetal presentation for home births specifically. Not confirmed to share mfr_fosterpraesentation’s DUP/RGAD SKS coding: this register predates the 2019+ restructuring entirely.
  • MISDANNELSER: Congenital malformations, by the variable name.
  • AMNITOMI_UNDER_FOEDSEL_HSP: Membrane rupture during labour (HSP), by the variable name - the same induction method mfr_nyfoedte.yaml’s Igangsaettelse_HSP describes for the 2019+ era.
  • FOEDSELSKODER: Plural in name; likely holds more than one delivery-related code per row rather than a single simple value, but this is not confirmed.
  • BESOEGHOSJORDEMODER: Visit(s) to a midwife, by the variable name.
  • BESOEGHOSLAEGE: Visit(s) to a doctor (general practitioner), by the variable name.
  • BESOEGHOSSPECIALLAEGE: Visit(s) to a specialist doctor, by the variable name.
  • TIMES: Hours, by the variable name - possibly labour duration, not confirmed.

No published source gives a data type for 32 of these 32 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: FK_MFR.

Joins to other registers:

  • FK_MFR joins to MFR (one-to-one).
  • CPR_MODER joins to BEF (many-to-one).

Worth knowing:

  • FK_MFR: By its name, a foreign key back to mfr.yaml’s own row for this birth. The exact column it matches on mfr.yaml’s side (assumed here to be cpr_barn, mfr.yaml’s own join_keys) is not confirmed by either variable list, since neither page documents the join.

Nyfoedte - Medical Birth Register, 2019 onwards

The current MFR. One row per newborn (live-born or stillborn, unified in one table for the first time - the 1997-2018 table above held only live births). Join Barn_* satellite tables via DW_EK_Nyfoedt, Mor_* satellite tables via DW_EK_Foedsel (see the ten satellite tables below). Nyfoedte itself already carries a curated subset of medical facts (diagnosis, weight, Apgar score, smoking status) that Sundhedsdatastyrelsen resolves from the underlying LPR3 contacts.

Numeric fields use -1 as “not stated”, not NA. Vaegt_Barn, Laengde_Barn, Hovedomfang, Abdominalomfang, Placentavaegt, Paritet, Apgarscore and BMI_Mor (as -1.0) all use this sentinel. A mean computed without recoding it first will be pulled sharply downward. Every stillbirth also gets Apgarscore = 0 by definition, not -1 - filter on LevendefoedtDoedfoedt before summarising Apgar scores.

Mother’s smoking status (Tobaksforbrug) uses two SKS code families for the same nine categories. DUT* before the LPR3 cutover (Feb/March 2019), RGAB* from it onwards - DUT20 and RGAB20 mean the same thing. See tobaksforbrug.yaml for the full mapping (resolved via the sksr package, since Sundhedsdatastyrelsen’s own documentation names both prefixes but not the per-code labels).

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
LevendefoedtDoedfoedt character code Live birth or stillbirth
CPRnummer_Barn character join key Child’s CPR-number
FoedselsDato_Barn date date Child’s date of birth
All other columns (67)
Column Type Role Label
DW_EK_Foedsel character join key Birth event key
Foedsel numeric code First-born-of-this-birth indicator
FoedselsAar numeric value Birth year
Gestationsalder numeric value Gestational age (days)
GestationsalderUger numeric value Gestational age (full weeks)
Foedested_Faktisk character code Actual place of birth
FoedselsDiagnose_Barn character code Child’s birth diagnosis
FoedselsDiagnose_Mor character code Mother’s birth diagnosis
Kejsersnit character code Caesarean section procedure code
Igangsaettelse_Medicinsk character code Medical labour induction
Igangsaettelse_HSP character code Labour induction by membrane rupture (HSP)
Igangsaettelse_Ballonkateter character code Labour induction by balloon catheter
PrimaerVandafgang character code Primary rupture of membranes (incl. PROM/PPROM)
Fosterpraesentation character code Fetal presentation
AntalBoernIFoedslen numeric value Number of children in this birth
AntalLevendefoedteIFoedslen numeric value Number of live-born children in this birth
AntalDoedfoedteIFoedslen numeric value Number of stillborn children in this birth
BarnsNummerIFoedslen numeric value Child’s number within this birth
Apgarscore numeric value 5-minute Apgar score
Vaegt_Barn numeric value Child’s birth weight (grams)
Laengde_Barn numeric value Child’s birth length (cm)
Hovedomfang numeric value Child’s head circumference (cm)
Abdominalomfang numeric value Child’s abdominal circumference (cm)
Placentavaegt numeric value Placental weight (grams)
Paritet numeric value Parity (completed pregnancies, incl. current)
Vaegt_Mor numeric value Mother’s pre-pregnancy weight (kg)
Hoejde_Mor numeric value Mother’s pre-pregnancy height (cm)
BMI_Mor numeric value Mother’s pre-pregnancy BMI
Tobaksforbrug character code Mother’s smoking status in pregnancy
AnsvarligRegion_Geo_Kode character code Geographic region of the reporting institution (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the reporting institution (text)
AnsvarligRegion_Org_Kode character code Organisational region of the reporting hospital (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the reporting hospital (text)
AnsvarligInstitution_Kode character code Reporting institution (code)
AnsvarligInstitution_Tekst character derived Reporting institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
SOR_EjerEnhedsType character code SOR owner type (public/private) of the reporting unit
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
DoedFoersteAar_Barn numeric value Days to the child’s death within its first year of life
DoedFoersteAar_Mor numeric value Days from birth to the mother’s death within the first year after
ErCPRnummerGyldigt_Barn character code Validity type of the child’s CPR-number
Koen_Barn character code Child’s sex
FoedselsTidspunkt character value Child’s time of birth
Kilde_Barn character code Source of the child’s birth record
IndberetningsSystem_Barn character code Reporting system for the child’s birth contact
DW_EK_Kontakt_Barn character code Child’s LPR birth contact key
DW_ID_Hjem_Barn character code Home/clinic birth paper-form key
DW_ID_Doed_Barn character code Stillbirth paper-form key
CPRnummer_Mor character join key Mother’s CPR-number
ErCPRnummerGyldigt_Mor character code Validity type of the mother’s CPR-number
Koen_Mor character code Sex on the mother’s CPR-like number
FoedselsDato_Mor date date Mother’s date of birth
Alder_Mor numeric value Mother’s age at the child’s birth
BopaelsKommune_Mor character code Mother’s municipality of residence at the child’s birth
BopaelsRegion_Mor character code Mother’s region of residence at the child’s birth
Kilde_Mor character code Source of the mother’s record
DW_EK_Kontakt_Mor character code Mother’s LPR birth contact key
CPRnummer_Far character join key Father’s CPR-number
ErCPRnummerGyldigt_Far character code Validity type of the father’s CPR-number
Koen_Far character code Sex on the father’s CPR-like number
FoedselsDato_Far date date Father’s date of birth
Alder_Far numeric value Father’s age at the child’s birth
Kilde_Far character code Source of the father’s record
  • Foedsel: Filter to Foedsel == 1 to count births instead of newborns: a twin birth otherwise contributes two rows to any count of “births”.
  • FoedselsDiagnose_Barn: D-prefixed like LPR (e.g. DZ389), not the plain WHO code cancer/ dodsaars use. See ICD codes and the D-prefix.
  • Kejsersnit: An open SKS procedure code space, not a small enumerated set: no code_system is attached here because the underlying classification is the general SKS procedure catalogue (see kont_type.yaml’s own reader_note on the same issue), not a birth-specific value list. A non-missing value means a caesarean happened; treat the specific KMCA* variant as a procedure detail, not a category to enumerate.
  • Igangsaettelse_Medicinsk: Multiple induction methods can co-occur and are reported as separate indicator columns (this one, Igangsaettelse_HSP, Igangsaettelse_Ballonkateter): they are not mutually exclusive categories of one variable.
  • Apgarscore: -1 means not stated, not a real score - exclude or recode before computing a mean. Every stillbirth is set to 0 by definition, not -1: a naive “average Apgar score” across LevendefoedtDoedfoedt values will be pulled down by stillbirths unless filtered first.
  • Vaegt_Barn: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Laengde_Barn: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Hovedomfang: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Abdominalomfang: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Placentavaegt: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Paritet: -1 means not stated. Also note the substitution rule above: this column is not always a direct report, it can be a computed fallback that only sees MFR’s own 2005+ history, undercounting a mother’s true parity if she had earlier children before 2005 or outside Denmark.
  • Vaegt_Mor: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • Hoejde_Mor: -1 means not stated. Recode before analysis, the same trap as Apgarscore above.
  • BMI_Mor: -1.0 means not stated, and is computed from Vaegt_Mor/Hoejde_Mor: if either of those is itself -1 (not stated), this column will be too. Bliddal et al. 2018 (mined for this guide) reports pre-pregnancy BMI as structurally, not randomly, missing before 2003 in the older MFR eras - the field did not exist yet, distinct from this -1 sentinel.
  • AnsvarligRegion_Geo_Kode: Not the same numbering as DST’s own reg code system (which uses 81-84): this is Sundhedsdatastyrelsen’s organisational region code, a different value space, despite both being called “region”. Do not join or compare against reg without confirming the mapping first. Missing for some home and clinic births.
  • AnsvarligInstitution_Kode: The code TYPE flips at the LPR3 cutover (Feb/March 2019): a SHAK hospital-department code before it, a SOR health-institution code after. AnsvarligInstitution_KodeType says which one a given row holds - check it before comparing codes across the boundary, since a SHAK code and a SOR code for the same physical hospital do not look alike.
  • DoedFoersteAar_Barn: NULL means no death within the first year, it is not a missing-data code.
  • DoedFoersteAar_Mor: NULL means no death within that year, it is not a missing-data code.
  • IndberetningsSystem_Barn: No code_system attached: unlike lprindberetningssystem on the LPR3 tables, Sundhedsdatastyrelsen’s own documentation gives only two examples here, not a closed list, and this column’s values are not confirmed to be identical to lprindberetningssystem’s (“LPR3”, “MiniPAS”, “LPR2”, “LPR1”) since this column also has to cover the non-LPR paper-form sources (Kilde_Barn = 2 or 3). Confirm with count(IndberetningsSystem_Barn) before filtering on it.
  • DW_EK_Kontakt_Barn: Only populated for LPR-sourced births (Kilde_Barn = 1): NULL for the home-birth and stillbirth paper-form cases, which have no LPR contact to key against. A join to lpr_a_kontakt on this column silently drops every paper-form birth.
  • CPRnummer_Mor: Since 2019, a birth counts even if the mother has no Danish CPR-number. Check ErCPRnummerGyldigt_Mor before joining this onward.
  • BopaelsRegion_Mor: Same caution as AnsvarligRegion_Geo_Kode: this does not look like DST’s own reg numbering (81-84). Not confirmed against reg, do not assume they are the same code space.
  • Kilde_Far: “9 = Uoplyst” (unknown paternity) is a real, common value here, not a data-quality problem to filter out - see mfr_kilde_forael.yaml.

Join key: CPRnummer_Barn.

Joins to other registers:

  • CPRnummer_Barn joins to BEF (many-to-one).
  • DW_EK_Kontakt_Barn joins to LPR_A_KONTAKT (many-to-one).
Value sets for the coded columns (10)
Code system Values
mfr_levendefoedt_doedfoedt 1 Levendefødt, 2 Dødfødt
mfr_foedested_faktisk 1 Hospital, 2 Fødeklinik, 3 Hjem, 4 Uden for hospital, fødeklinik og hjem, 9 Uoplyst
icd10 Not listed here - see DST’s classification
mfr_fosterpraesentation DUP01 regelmæssig baghovedstilling, RGAD01 regelmæssig baghovedstilling, DUP02 uregelmæssig baghovedstilling, RGAD02 uregelmæssig baghovedstilling, DUP03 dyb tværstand, RGAD03 dyb tværstand, DUP04 forissepræsentation, RGAD04 forissepræsentation, DUP05 pandepræsentation, RGAD05 pandepræsentation, DUP06 ansigtspræsentation, RGAD06 ansigtspræsentation, DUP07 ren sædepræsentation, RGAD07 ren sædepræsentation, DUP08 fuldstændig sæde-fod-præsentation, RGAD08 fuldstændig sæde-fod-præsentation, DUP09 ufuldstændig sæde-fod-præsentation, RGAD09 ufuldstændig sæde-fod-præsentation, DUP10 fodpræsentation, RGAD10 fodpræsentation, DUP11 anden underkropspræsentation, RGAD11 anden underkropspræsentation, DUP12 tværleje/skråleje, RGAD12 tværleje/skråleje, DUP13 høj lige stand, RGAD13 høj lige stand, DUP14 asynklitisk hovedpræsentation, RGAD14 asynklitisk hovedpræsentation, DUP15 uspecificeret hovedpræsentation, RGAD15 uspecificeret hovedpræsentation, DUP16 uspecificeret underkropspræsentation, RGAD16 uspecificeret underkropspræsentation, DUP99 fosterpræsentation uden specifikation, RGAD99 fosterpræsentation uoplyst
tobaksforbrug DUT00 Moder ryger ikke, RGAB00 moder ryger ikke, DUT10 Moder ophørt med rygning i 1. trimester, RGAB10 moder ophørt med rygning i 1. trimester, DUT11 Moder ophørt med rygning efter 1. trimester, RGAB11 moder ophørt med rygning efter 1. trimester, DUT20 Moder ryger op til 5 cigaretter dagligt, RGAB20 moder ryger op til 5 cigaretter dagligt, DUT21 Moder ryger fra 6-10 cigaretter dagligt, RGAB21 moder ryger fra 6-10 cigaretter dagligt, DUT22 Moder ryger fra 11-20 cigaretter dagligt, RGAB22 moder ryger fra 11-20 cigaretter dagligt, DUT23 Moder ryger over 20 cigaretter dagligt, RGAB23 moder ryger over 20 cigaretter dagligt, DUT29 Moder ryger, mængde ikke oplyst, RGAB29 moder ryger, mængde ikke oplyst, DUT99 Moders rygestatus uoplyst, RGAB99 moders rygestatus uoplyst
mfr_er_cprnummer_gyldigt Gyldig hos CPR Gyldig hos CPR, Udgået hos CPR Udgået hos CPR, Erstatnings CPR Erstatnings CPR, Fiktivt Fiktivt, Andet CPR Andet CPR
mfr_koen K Kvinde, M Mand, Ukendt Ukendt
mfr_kilde_barn 1 Landspatientregisteret (LPR), 2 Hjemmefødselsblanket, 3 Dødfødselsblanket
kom Not listed here - see DST’s classification
mfr_kilde_forael 1 Landspatientregisteret (LPR), 2 Hjemmefødselsblanket, 3 Dødfødselsblanket, 4 CPR, 9 Uoplyst
  • mfr_levendefoedt_doedfoedt: A query written against the old 1997-2018 “Levendefødte” table implicitly filtered to live births by construction. The same query pointed at mfr_nyfoedte without LevendefoedtDoedfoedt == 1 will silently pull in stillbirths too. Apgarscore is set to 0 for every stillbirth rather than left missing, which will also distort a naive mean/summary of Apgar scores computed without this filter.
  • mfr_foedested_faktisk: Do not try to derive this yourself from FoedselsDiagnose_Barn alone: the mapping from birth-diagnosis code to actual birthplace changed at two different boundaries (2012, and the LPR3 cutover in Feb/March 2019), and Sundhedsdatastyrelsen has already resolved that history into this single column. Recomputing it from the diagnosis code with only the current (post-2019) mapping will misclassify pre-2012 home births as “outside hospital, birth clinic and home”.
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • mfr_fosterpraesentation: Recorded on the child’s own fødselskontakt (or as an add-on to it before LPR3), not the mother’s, even though fetal presentation is clinically a fact about the pregnancy and delivery. Join through DW_EK_Nyfoedt if cross-referencing against Barn_* satellite tables, not DW_EK_Foedsel.
  • tobaksforbrug: Bliddal et al. 2018 (mined earlier for this guide) reports smoking status as 100% missing before late 1997 and notes the field is otherwise reliably recorded once it exists. That predates both DUT and RGAB: an analysis spanning multiple decades needs to know smoking status went through at least two encodings (pre-1997: absent; 1997 to the LPR3 cutover: DUT; LPR3 cutover onwards: RGAB), not one stable variable. When multiple smoking-status sources exist for the same birth, Sundhedsdatastyrelsen resolves them in a fixed order (result/add-on tied to the primary birth record over other records, “komplet” over “inkomplet” reporting status, then the heaviest smoking category over lighter ones) - see the MFR 2019+ documentation for the exact tie-break rules if you need to reproduce Tobaksforbrug from the underlying satellite tables yourself.
  • mfr_er_cprnummer_gyldigt: Only “Gyldig hos CPR” is guaranteed to resolve when joining to bef or any other CPR-keyed register: an “Udgået hos CPR” number identifies a real person but under a number CPR itself has since retired (e.g. after a birth-date correction), while “Erstatnings CPR” and “Fiktivt” numbers were never real CPR-numbers at all and will join to nothing. Check this column before joining CPRnummer_Barn, _Mor, or _Far onwards, rather than assuming every value in those columns is a working key.
  • mfr_koen: For the child, this is derived from Dim.Borger.KoenID plus, for stillbirths reported on paper, the stillbirth form or the CPR-like number itself - not purely a CPR lookup, since a stillborn child may never receive one. For the mother and father, it is a straight lookup on their own CPR-derived sex, so Koen_Far being “Ukendt” or missing does not imply anything about the birth itself, only that paternal identity was not established.
  • mfr_kilde_barn: This value gates which other columns are populated at all. DW_EK_Kontakt_Barn is only set when this is “1”; DW_ID_Hjem_Barn only when this is “2”; and DW_ID_Doed_Barn when this is “3” (or when a paper stillbirth form supplements an LPR3 birth record). A join to Barn_Kontakter or any other LPR-sourced satellite table will silently return nothing for rows where Kilde_Barn is “2” or “3”, since those children have no LPR contact at all.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • mfr_kilde_forael: “9 = Uoplyst” exists for a parent (most often the father) but has no counterpart on the child’s own Kilde_Barn: a birth with no determinable source simply is not in the register at all. Treat Kilde_Far == “9” as a real, common case (unknown paternity), not a data-quality flag to filter out.

Where these values come from:

Worth knowing:

  • DW_EK_Nyfoedt: One row per newborn, not per birth: a twin birth produces two rows sharing one DW_EK_Foedsel but each with its own DW_EK_Nyfoedt. Use DW_EK_Nyfoedt to join Barn_* satellite tables, DW_EK_Foedsel to join Mor_* satellite tables.
  • CPRnummer_Barn: A stillborn child may never receive a real CPR-number. Check ErCPRnummerGyldigt_Barn before joining this onward to bef or any other CPR-keyed register.
The ten satellite tables (Barn_/Mor_ diagnoses, procedures, contacts, course elements, results)

Same idea as lpr_a_kontakt/lpr_a_diagnose/lpr_a_procregistrering, just scoped to birth-related contacts and split by child (Barn_*) vs mother (Mor_*). Join Barn_* tables to Nyfoedte via DW_EK_Nyfoedt, Mor_* tables via DW_EK_Foedsel.

Barn_Forloeb / Mor_Forloeb - course elements

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
All other columns (29)
Column Type Role Label
ForloebLabel character code Course-element label
AfslutningsMaade character code How the course element ended
ForloebReferenceMaade character code How the course element was referenced
StartDato_Forloeb date date Course-element start date
StartTidspunkt_Forloeb character value Course-element start time
SlutDato_Forloeb date date Course-element end date
SlutTidspunkt_Forloeb character value Course-element end time
HenvisningMaade character code Referral method
HenvisningsDiagnose character code Referral diagnosis
Dato_Henvisning date date Referral date
Tidspunkt_Henvisning character value Referral time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
IndberetningsSystem character code Reporting system for the course element
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Forloeb character code LPR course-element key
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • PrioriteretFoedselsanmeldelse: When a child has more than one candidate birth contact, only one is “prioritised” into Nyfoedte’s own columns. Filter to == 1 to match exactly what Nyfoedte itself reports; the other rows are real but describe contacts Sundhedsdatastyrelsen did not choose as the authoritative birth record.

Join key: DW_EK_Nyfoedt.

Joins to other registers:

  • DW_EK_Nyfoedt joins to MFR_NYFOEDTE (many-to-one).
Value sets for the coded columns (2)
Code system Values
icd10 Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Column Type Role Label
DW_EK_Foedsel character join key Birth event key
All other columns (29)
Column Type Role Label
ForloebLabel character code Course-element label
AfslutningsMaade character code How the course element ended
ForloebReferenceMaade character code How the course element was referenced
StartDato_Forloeb date date Course-element start date
StartTidspunkt_Forloeb character value Course-element start time
SlutDato_Forloeb date date Course-element end date
SlutTidspunkt_Forloeb character value Course-element end time
HenvisningMaade character code Referral method
HenvisningsDiagnose character code Referral diagnosis
Dato_Henvisning date date Referral date
Tidspunkt_Henvisning character value Referral time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
IndberetningsSystem character code Reporting system for the course element
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Forloeb character code LPR course-element key
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice of birth contact, same logic as mfr_barn_forloeb.yaml.

Join key: DW_EK_Foedsel.

Joins to other registers:

  • DW_EK_Foedsel joins to MFR_NYFOEDTE (many-to-one).
Value sets for the coded columns (2)
Code system Values
icd10 Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Worth knowing:

  • DW_EK_Foedsel: Filter mfr_nyfoedte to Foedsel == 1 before joining this table onward if you want one row per birth: otherwise a twin birth’s shared DW_EK_Foedsel matches twice, once per twin.

Barn_Kontakter / Mor_Kontakter - contacts

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
StartDato_Kontakt date date Contact start date
All other columns (37)
Column Type Role Label
AktionsDiagnose character code Action diagnosis
KontaktAarsag character code Contact reason
Prioritet character code Priority (acute/planned)
KontaktType character code Contact type
StartTidspunkt_Kontakt character value Contact start time
SlutDato_Kontakt date date Contact end date
SlutTidspunkt_Kontakt character value Contact end time
Alder_Ind_Aar numeric value Child’s age in years at contact start
Alder_Ind_Dage numeric value Child’s age in days at contact start
Alder_Ud_Aar numeric value Child’s age in years at contact end
Alder_Ud_Dage numeric value Child’s age in days at contact end
HenvisningsMaade character code Referral method
HenvisningsDiagnose character code Referral diagnosis
Dato_Henvisning date date Referral date
Tidspunkt_Henvisning character value Referral time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
ForloebLabel character code Course-element label the contact belongs to
StartDato_Forloeb date date Start date of the course element the contact belongs to
SlutDato_Forloeb date date End date of the course element the contact belongs to
IndberetningsSystem character code Reporting system for the contact
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character join key LPR contact key
DW_EK_Forloeb character code LPR course-element key this contact belongs to
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice of birth contact when a child has more than one candidate. Same logic as mfr_barn_forloeb.yaml’s column of the same name.
  • DW_EK_Kontakt: Same key space as lpr_a_kontakt’s dw_ek_kontakt: a birth-related contact found here should also be findable there, if you need LPR detail this satellite table does not carry.

Join key: DW_EK_Nyfoedt.

Joins to other registers:

  • DW_EK_Nyfoedt joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Forloeb joins to MFR_BARN_FORLOEB (many-to-one).
Value sets for the coded columns (3)
Code system Values
icd10 Not listed here - see DST’s classification
kont_type Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • kont_type: ALCA00 means physical attendance, which is the closest LPR3 gets to LPR2’s inpatient flag. It marks attendance, not admission, so a study that treats it as “was admitted” will include outpatient visits. Check what your own delivery holds before filtering: single digits and SKS codes have been seen side by side in the same year, so kont_type == "ALCA00" can silently drop rows that are the same kind of contact recorded in the other form. Cross-tabulate it against lprindberetningssystem first. MiniPAS was the route private providers reported through, so the two forms are not only two notations, they are also two different parts of the health service.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Column Type Role Label
DW_EK_Foedsel character join key Birth event key
StartDato_Kontakt date date Contact start date
All other columns (33)
Column Type Role Label
AktionsDiagnose character code Action diagnosis
KontaktAarsag character code Contact reason
Prioritet character code Priority (acute/planned)
KontaktType character code Contact type
StartTidspunkt_Kontakt character value Contact start time
SlutDato_Kontakt date date Contact end date
SlutTidspunkt_Kontakt character value Contact end time
HenvisningsMaade character code Referral method
HenvisningsDiagnose character code Referral diagnosis
Dato_Henvisning date date Referral date
Tidspunkt_Henvisning character value Referral time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
ForloebLabel character code Course-element label the contact belongs to
StartDato_Forloeb date date Start date of the course element the contact belongs to
SlutDato_Forloeb date date End date of the course element the contact belongs to
IndberetningsSystem character code Reporting system for the contact
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character join key LPR contact key
DW_EK_Forloeb character code LPR course-element key this contact belongs to
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Foedsel.

Joins to other registers:

  • DW_EK_Foedsel joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Forloeb joins to MFR_MOR_FORLOEB (many-to-one).
Value sets for the coded columns (3)
Code system Values
icd10 Not listed here - see DST’s classification
kont_type Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • kont_type: ALCA00 means physical attendance, which is the closest LPR3 gets to LPR2’s inpatient flag. It marks attendance, not admission, so a study that treats it as “was admitted” will include outpatient visits. Check what your own delivery holds before filtering: single digits and SKS codes have been seen side by side in the same year, so kont_type == "ALCA00" can silently drop rows that are the same kind of contact recorded in the other form. Cross-tabulate it against lprindberetningssystem first. MiniPAS was the route private providers reported through, so the two forms are not only two notations, they are also two different parts of the health service.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Worth knowing:

  • DW_EK_Foedsel: Filter mfr_nyfoedte to Foedsel == 1 before joining onward for multiples, same as mfr_mor_forloeb.yaml.

Barn_Diagnoser / Mor_Diagnoser - diagnoses

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
DiagnoseKode character code Diagnosis, contact-reason, or add-on code
DiagnoseType character code Diagnosis role
All other columns (18)
Column Type Role Label
DiagnoseType_Tekst character derived Diagnosis role (text)
SenereAfkraeftet character code Later disproven
DiagnoseKode_Parent character code Parent diagnosis code (when DiagnoseType = +)
DiagnoseType_Parent character code Role of the parent diagnosis (when DiagnoseType = +)
DiagnoseType_Parent_Tekst character derived Role of the parent diagnosis, text (when DiagnoseType = +)
SenereAfkraeftet_Parent character code Whether the parent diagnosis was later disproven (when DiagnoseType = +)
AktionsDiagnose character code Action diagnosis of the contact this row belongs to
StartDato_Kontakt date date Start date of the contact this row belongs to
SlutDato_Kontakt date date End date of the contact this row belongs to
ForloebLabel character code Course-element label (via the contact)
StartDato_Forloeb date date Start date of the course element (via the contact)
SlutDato_Forloeb date date End date of the course element (via the contact)
Indberetningssystem character code Reporting system for the diagnosis
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character join key LPR contact key
DW_EK_Forloeb character code LPR course-element key
DW_ID_Hjem character code Home/clinic birth paper-form key
DW_ID_Doed character code Stillbirth paper-form key
  • SenereAfkraeftet: A pre-LPR3 “Nej” here does not mean the diagnosis was verified, it means the concept of tracking retraction did not exist yet and everything defaults to “Nej”. Do not treat pre- and post-cutover “Nej” as equally informative.
  • DiagnoseType_Parent: A narrower set than the full mfr_diagnose_type lookup: only A/B/C/G/H/M are valid here (no K or +), since an add-on cannot itself be a contact reason or another add-on.
  • Indberetningssystem: No code_system attached, same reasoning as mfr_nyfoedte.yaml’s IndberetningsSystem_Barn: this column also covers non-LPR paper-form sources, so it is not confirmed to share lprindberetningssystem’s exact value set. Confirm with count(Indberetningssystem) before filtering on it.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Nyfoedt.

Joins to other registers:

  • DW_EK_Nyfoedt joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_BARN_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_BARN_FORLOEB (many-to-one).
Value sets for the coded columns (2)
Code system Values
icd10 Not listed here - see DST’s classification
mfr_diagnose_type A Aktionsdiagnose, B Bidiagnose, C Komplikation, G Grundmorbus, H Henvisningsdiagnose, K Kontaktårsag, M Midlertidig diagnose, + Tillægskode, Lokal recidiv, Metastase eller Sideangivelse
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • mfr_diagnose_type: When DiagnoseType is “+”, DiagnoseKode is an add-on that only makes sense attached to another diagnosis: that parent diagnosis, its own type, and whether it was later disproven live in DiagnoseKode_Parent, DiagnoseType_Parent and SenereAfkraeftet_Parent on the same row, not in DiagnoseKode itself. tobaksforbrug’s DUT* codes and mfr_fosterpraesentation’s DUP* codes are exactly this kind of “+” add-on code before the LPR3 cutover.

Where these values come from:

Worth knowing:

  • DiagnoseKode: code_system: icd10 fits the diagnosis case only: this column also holds non-ICD-10 SKS add-on and contact-reason codes (see DiagnoseType), which will not resolve against the ICD-10 lookup. Check DiagnoseType before assuming a value here is a diagnosis.
Column Type Role Label
DW_EK_Foedsel character join key Birth event key
DiagnoseKode character code Diagnosis, contact-reason, or add-on code
DiagnoseType character code Diagnosis role
All other columns (18)
Column Type Role Label
DiagnoseType_Tekst character derived Diagnosis role (text)
SenereAfkraeftet character code Later disproven
DiagnoseKode_Parent character code Parent diagnosis code (when DiagnoseType = +)
DiagnoseType_Parent character code Role of the parent diagnosis (when DiagnoseType = +)
DiagnoseType_Parent_Tekst character derived Role of the parent diagnosis, text (when DiagnoseType = +)
SenereAfkraeftet_Parent character code Whether the parent diagnosis was later disproven (when DiagnoseType = +)
AktionsDiagnose character code Action diagnosis of the contact this row belongs to
StartDato_Kontakt date date Start date of the contact this row belongs to
SlutDato_Kontakt date date End date of the contact this row belongs to
ForloebLabel character code Course-element label (via the contact)
StartDato_Forloeb date date Start date of the course element (via the contact)
SlutDato_Forloeb date date End date of the course element (via the contact)
Indberetningssystem character code Reporting system for the diagnosis
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character join key LPR contact key
DW_EK_Forloeb character code LPR course-element key
DW_ID_Hjem character code Home/clinic birth paper-form key
DW_ID_Doed character code Stillbirth paper-form key
  • DiagnoseType_Parent: Narrower set (A/B/C/G/H/M only), same as mfr_barn_diagnoser.yaml’s DiagnoseType_Parent.
  • Indberetningssystem: No code_system attached, same reasoning as mfr_barn_diagnoser.yaml’s Indberetningssystem.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Foedsel.

Joins to other registers:

  • DW_EK_Foedsel joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_MOR_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_MOR_FORLOEB (many-to-one).
Value sets for the coded columns (2)
Code system Values
icd10 Not listed here - see DST’s classification
mfr_diagnose_type A Aktionsdiagnose, B Bidiagnose, C Komplikation, G Grundmorbus, H Henvisningsdiagnose, K Kontaktårsag, M Midlertidig diagnose, + Tillægskode, Lokal recidiv, Metastase eller Sideangivelse
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • mfr_diagnose_type: When DiagnoseType is “+”, DiagnoseKode is an add-on that only makes sense attached to another diagnosis: that parent diagnosis, its own type, and whether it was later disproven live in DiagnoseKode_Parent, DiagnoseType_Parent and SenereAfkraeftet_Parent on the same row, not in DiagnoseKode itself. tobaksforbrug’s DUT* codes and mfr_fosterpraesentation’s DUP* codes are exactly this kind of “+” add-on code before the LPR3 cutover.

Where these values come from:

Worth knowing:

  • DiagnoseKode: Same caveat as mfr_barn_diagnoser.yaml’s DiagnoseKode: code_system: icd10 fits only the diagnosis case. Check DiagnoseType first.

Barn_Procedurer / Mor_Procedurer - procedures

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
ProcedureKode character code Procedure, add-on, or indication code
ProcedureType character code Procedure role
All other columns (34)
Column Type Role Label
ProcedureType_Tekst character derived Procedure role (text)
ProcedureKode_Parent character code Parent procedure code (when ProcedureType = +)
ProcedureType_Parent character code Role of the parent procedure (when ProcedureType = +)
ProcedureType_Parent_Tekst character derived Role of the parent procedure, text (when ProcedureType = +)
StartDato_Procedure date date Procedure start date
StartTidspunkt_Procedure character value Procedure start time
SlutDato_Procedure date date Procedure end date
SlutTidspunkt_Procedure character value Procedure end time
ProducerendeRegion_Kode character code Geographic region of the producing unit (code, legacy duplicate)
ProducerendeRegion_Geo_Kode character code Geographic region of the producing unit (code)
ProducerendeRegion_Geo_Tekst character derived Geographic region of the producing unit (text)
ProducerendeRegion_Org_Kode character code Organisational region of the producing unit (code)
ProducerendeRegion_Org_Tekst character derived Organisational region of the producing unit (text)
ProducerendeInstitution_Kode character code Producing institution (code)
ProducerendeInstitution_Tekst character derived Producing institution (text)
ProducerendeInstitution_KodeType character code Code type of ProducerendeInstitution_Kode
EnhedensSpecialer character value Specialties of the producing unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the producing unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
AktionsDiagnose character code Action diagnosis of the contact this procedure belongs to
StartDato_Kontakt date date Start date of the contact this procedure belongs to
SlutDato_Kontakt date date End date of the contact this procedure belongs to
ForloebLabel character code Course-element label
StartDato_Forloeb date date Start date of the course element
SlutDato_Forloeb date date End date of the course element
IndberetningsSystem character code Reporting system for the procedure
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character code LPR contact key
DW_EK_Forloeb character code LPR course-element key
  • ProcedureType_Parent: Narrower than the full mfr_procedure_type lookup: after the LPR3 cutover only “P” is valid here (not “I”), before it only D/P/V - an add-on cannot itself be another add-on or, post-cutover, an indication.
  • ProducerendeRegion_Kode: Appears to duplicate ProducerendeRegion_Geo_Kode exactly. Check both against colnames() on your own delivery before assuming which one to use.
  • ProducerendeRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • ProducerendeInstitution_Kode: SHAK before the LPR3 cutover, SOR from it - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Nyfoedt.

Joins to other registers:

  • DW_EK_Nyfoedt joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_BARN_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_BARN_FORLOEB (many-to-one).
Value sets for the coded columns (3)
Code system Values
mfr_procedure_type I Indikation, P Procedure (efter LPR3) / Vigtigste operation i et operativt indgreb (før LPR3), D Deloperation, anden operation(er) i et operativt indgreb, V Vigtigste operation i en afsluttet kontakt, + Tillægskode, Samhørende operation eller Sideangivelse (før LPR3) / Tillægskode, Anvendt kontrast, Handlingsspecifikation, Personalekategori eller Sideangivelse (efter LPR3)
icd10 Not listed here - see DST’s classification
lprindberetningssystem LPR3, MiniPAS, LPR2, LPR1
  • mfr_procedure_type: Reading “P” as one stable category across the whole table conflates “the main operation” (pre-LPR3, one of three specific operation roles) with “any procedure at all” (post-LPR3, the default value for most rows). This will inflate counts of “main operations” for LPR3-era rows if not checked against IndberetningsSystem first. See ProcedureType_Parent for the narrower set of types (post-LPR3: only “P”; pre-LPR3: D/P/V) that a “+” add-on can actually attach to.
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • lprindberetningssystem: Confirm the exact strings with count(lprindberetningssystem) before relying on “LPR2” or “LPR1” in a filter: they are well-established as concepts in this guide, but nobody has pasted the literal value back from DARTER the way pitfall 5 did for “LPR3”. “MiniPAS” is safe to rely on, since kont_type.yaml’s coalescing logic already depends on it being exactly that string. This column is unrelated to LPR_F vs LPR_A: that choice is made before you open a file, this one lives inside the file you already chose.

Where these values come from:

Worth knowing:

  • ProcedureKode: No code_system attached: the SKS procedure catalogue is an open space, the same reasoning as mfr_nyfoedte.yaml’s Kejsersnit column and kont_type.yaml’s own reader_note on the same issue.
Column Type Role Label
DW_EK_Foedsel character join key Birth event key
ProcedureKode character code Procedure, add-on, or indication code
ProcedureType character code Procedure role
All other columns (34)
Column Type Role Label
ProcedureType_Tekst character derived Procedure role (text)
ProcedureKode_Parent character code Parent procedure code (when ProcedureType = +)
ProcedureType_Parent character code Role of the parent procedure (when ProcedureType = +)
ProcedureType_Parent_Tekst character derived Role of the parent procedure, text (when ProcedureType = +)
StartDato_Procedure date date Procedure start date
StartTidspunkt_Procedure character value Procedure start time
SlutDato_Procedure date date Procedure end date
SlutTidspunkt_Procedure character value Procedure end time
ProducerendeRegion_Geo_Kode character code Geographic region of the producing unit (code)
ProducerendeRegion_Geo_Tekst character derived Geographic region of the producing unit (text)
ProducerendeRegion_Org_Kode character code Organisational region of the producing unit (code)
ProducerendeRegion_Org_Tekst character derived Organisational region of the producing unit (text)
ProducerendeInstitution_Kode character code Producing institution (code)
ProducerendeInstitution_Tekst character derived Producing institution (text)
ProducerendeInstitution_KodeType character code Code type of ProducerendeInstitution_Kode
EnhedensSpecialer character value Specialties of the producing unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the producing unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
AktionsDiagnose character code Action diagnosis of the contact this procedure belongs to
StartDato_Kontakt date date Start date of the contact this procedure belongs to
SlutDato_Kontakt date date End date of the contact this procedure belongs to
ForloebLabel character code Course-element label
StartDato_Forloeb date date Start date of the course element
SlutDato_Forloeb date date End date of the course element
IndberetningsSystem character code Reporting system for the procedure
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character code LPR contact key
DW_EK_Forloeb character code LPR course-element key
DW_ID_Hjem character code Home/clinic birth paper-form key
  • ProcedureType_Parent: Narrower set, same as mfr_barn_procedurer.yaml’s ProcedureType_Parent.
  • ProducerendeRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • ProducerendeInstitution_Kode: SHAK before the LPR3 cutover, SOR from it, local code for paper-form procedures - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode for the SHAK/SOR half.
  • IndberetningsSystem: Unlike mfr_barn_procedurer.yaml’s IndberetningsSystem (examples only LPR2/LPR3), this column’s examples include paper-form sources, so no code_system is attached - not confirmed to share lprindberetningssystem’s exact value set.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Foedsel.

Joins to other registers:

  • DW_EK_Foedsel joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_MOR_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_MOR_FORLOEB (many-to-one).
Value sets for the coded columns (2)
Code system Values
mfr_procedure_type I Indikation, P Procedure (efter LPR3) / Vigtigste operation i et operativt indgreb (før LPR3), D Deloperation, anden operation(er) i et operativt indgreb, V Vigtigste operation i en afsluttet kontakt, + Tillægskode, Samhørende operation eller Sideangivelse (før LPR3) / Tillægskode, Anvendt kontrast, Handlingsspecifikation, Personalekategori eller Sideangivelse (efter LPR3)
icd10 Not listed here - see DST’s classification
  • mfr_procedure_type: Reading “P” as one stable category across the whole table conflates “the main operation” (pre-LPR3, one of three specific operation roles) with “any procedure at all” (post-LPR3, the default value for most rows). This will inflate counts of “main operations” for LPR3-era rows if not checked against IndberetningsSystem first. See ProcedureType_Parent for the narrower set of types (post-LPR3: only “P”; pre-LPR3: D/P/V) that a “+” add-on can actually attach to.
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.

Where these values come from:

Worth knowing:

  • ProcedureKode: No code_system attached, same reasoning as mfr_barn_procedurer.yaml’s ProcedureKode.

Barn_Resultater / Mor_Resultater - results

ResultatVaerdi is polymorphic. Depending on ResultatType, it holds an SKS code, an integer, a boolean, a decimal, a datetime, or a text string. Nyfoedte’s own resolved columns (Vaegt_Barn, Apgarscore, Tobaksforbrug’s RGAB* half, and more) are all built from rows in these two tables. Branch on ResultatType before parsing ResultatVaerdi.

Column Type Role Label
DW_EK_Nyfoedt character join key Newborn key
ResultatType character code Result type
All other columns (32)
Column Type Role Label
ResultatIndberetningsType character code Result-report type
ResultatIndberetningsStatus character code Result-report status (complete/incomplete)
ResultatVaerdi character value Result value (polymorphic)
Dato_Resultat date date Result date
Tidspunkt_Resultat character value Result time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
AktionsDiagnose character code Action diagnosis of the contact this result belongs to
StartDato_Kontakt date date Start date of the contact this result belongs to
SlutDato_Kontakt date date End date of the contact this result belongs to
ForloebLabel character code Course-element label
StartDato_Forloeb date date Start date of the course element
SlutDato_Forloeb date date End date of the course element
IndberetningsSystem character code Reporting system for the result
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character code LPR contact key
DW_EK_Forloeb character code LPR course-element key
DW_ID_Hjem character code Home/clinic birth paper-form key
DW_ID_Doed character code Stillbirth paper-form key
  • ResultatIndberetningsStatus: Several of mfr_nyfoedte’s own resolved columns (Tobaksforbrug, Vaegt_Barn, Hoejde_Mor, and others) prioritise “komplet” (RAS01) results over “inkomplet” (RAS00) ones when more than one result exists for the same fact. Reproducing that resolution logic yourself means checking this column, not just the newest result.
  • ResultatVaerdi: Reading this column as one consistent type will fail or silently coerce: for a ResultatType of RDA39 (weight) it is an integer number of grams, for RDA25 (smoking) or RDA41 (birthplace) it is itself an SKS code (RGAB/RGAE), for some boolean-style results 0 means “unknown” rather than “false” (not the usual R convention). Branch on ResultatType before parsing ResultatVaerdi, never parse it generically across the whole table.
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it, local code for paper-form results - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode for the SHAK/SOR half.
  • IndberetningsSystem: No code_system attached, same reasoning as the diagnosis tables’ IndberetningsSystem: this column includes paper-form sources, unlike Forloeb/Kontakter/Procedurer’s version which only exemplifies LPR2/LPR3.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Nyfoedt.

Joins to other registers:

  • DW_EK_Nyfoedt joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_BARN_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_BARN_FORLOEB (many-to-one).
Value sets for the coded columns (1)
Code system Values
icd10 Not listed here - see DST’s classification
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.

Where these values come from:

Worth knowing:

  • ResultatType: No code_system attached: this is an open SKS result-type catalogue, not a small enumerated set, the same reasoning as ProcedureKode. Each RDAnn value determines both what ResultatVaerdi means and what data type it holds - see that column’s reader_note.
Column Type Role Label
DW_EK_Foedsel character join key Birth event key
ResultatType character code Result type
All other columns (31)
Column Type Role Label
ResultatIndberetningsType character code Result-report type
ResultatIndberetningsStatus character code Result-report status (complete/incomplete)
ResultatVaerdi character value Result value (polymorphic)
Dato_Resultat date date Result date
Tidspunkt_Resultat character value Result time
AnsvarligRegion_Geo_Kode character code Geographic region of the responsible unit (code)
AnsvarligRegion_Geo_Tekst character derived Geographic region of the responsible unit (text)
AnsvarligRegion_Org_Kode character code Organisational region of the responsible unit (code)
AnsvarligRegion_Org_Tekst character derived Organisational region of the responsible unit (text)
AnsvarligInstitution_Kode character code Responsible institution (code)
AnsvarligInstitution_Tekst character derived Responsible institution (text)
AnsvarligInstitution_KodeType character code Code type of AnsvarligInstitution_Kode
EnhedensSpecialer character value Specialties of the responsible unit
SOR_EjerEnhedsType character code SOR owner type (public/private) of the responsible unit
SOR_EnhedsType character code SOR unit type (clinical/administrative)
SOR_SundhedsInstitution character code SOR health institution code
SOR_Enhed character code SOR unit code
SHAK_Sygehus character code SHAK hospital code (4 characters)
SHAK_Afdeling character code SHAK department code (6 characters)
SHAK_Afsnit character code SHAK ward code (7 characters)
AktionsDiagnose character code Action diagnosis of the contact this result belongs to
StartDato_Kontakt date date Start date of the contact this result belongs to
SlutDato_Kontakt date date End date of the contact this result belongs to
ForloebLabel character code Course-element label
StartDato_Forloeb date date Start date of the course element
SlutDato_Forloeb date date End date of the course element
IndberetningsSystem character code Reporting system for the result
PrioriteretFoedselsanmeldelse numeric code Priority birth-record indicator
DW_EK_Kontakt character code LPR contact key
DW_EK_Forloeb character code LPR course-element key
DW_ID_Hjem character code Home/clinic birth paper-form key
  • ResultatIndberetningsStatus: See mfr_barn_resultater.yaml’s ResultatIndberetningsStatus for the resolution-priority explanation - the same rule applies here for Vaegt_Mor, Hoejde_Mor and others.
  • ResultatVaerdi: Branch on ResultatType before parsing, same trap as mfr_barn_resultater.yaml’s ResultatVaerdi.
  • AnsvarligRegion_Geo_Kode: Not DST’s reg numbering - see mfr_nyfoedte.yaml’s AnsvarligRegion_Geo_Kode.
  • AnsvarligInstitution_Kode: SHAK before the LPR3 cutover, SOR from it, local code for paper-form results - see mfr_nyfoedte.yaml’s AnsvarligInstitution_Kode.
  • IndberetningsSystem: No code_system attached, same reasoning as mfr_barn_resultater.yaml’s IndberetningsSystem.
  • PrioriteretFoedselsanmeldelse: Filter to == 1 to reproduce Nyfoedte’s own choice, same logic as the other satellite tables.

Join key: DW_EK_Foedsel.

Joins to other registers:

  • DW_EK_Foedsel joins to MFR_NYFOEDTE (many-to-one).
  • DW_EK_Kontakt joins to MFR_MOR_KONTAKTER (many-to-one).
  • DW_EK_Forloeb joins to MFR_MOR_FORLOEB (many-to-one).
Value sets for the coded columns (1)
Code system Values
icd10 Not listed here - see DST’s classification
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.

Where these values come from:

Worth knowing:

  • ResultatType: No code_system attached, same reasoning as mfr_barn_resultater.yaml’s ResultatType.

MFR marker sub-cuts - the detail behind the flags

Nineteen of mfr’s own MARKOER_* columns above are flags only - the actual SKS-coded finding behind each one is published as its own separate DST dataset, joined back to mfr via FK_MFR. Confirmed against DST’s full 531-register order list (Bestillingsliste.xlsx) on 2026-09-12, the same “home births” relationship MFRHJMFO already has to mfr (see above).

DST publishes no labels or value definitions for any column in any of these 19 datasets. Two carry a genuine extra measurement alongside the SKS code (MFRBLODM’s measured blood-loss amount, MFRNVLAN’s pH/base excess); the rest are three columns wide: the SKS code, its type, and the foreign key back to mfr.

All 19 marker sub-cuts
Dataset Backs mfr’s flag What it holds Coverage
MFRACCRE markoer_accreta Placenta accreta 1997-2018
MFRAKMPL markoer_andre_foedselskomplikati Other birth complications 1997-2018
MFRANAES markoer_anaestesi_til_operation Anaesthesia for an operation 2000-2018
MFRBLODM markoer_post_partum_bloedning Postpartum blood loss, with the measured amount 2009-2018
MFRBRIST markoer_perineal_bristning Perineal tears 1997-2018
MFRCARDI markoer_cardiomyopati Cardiomyopathy 1997-2018
MFRGKMPL markoer_graviditetskomplikatio Pregnancy complications 1997-2018
MFRHAEMO markoer_haemoperitoneum Haemoperitoneum 1997-2018
MFRIGANG markoer_igangsaettelse Labour induction 1997-2018
MFRINFEK markoer_infektioner Infections 1997-2018
MFRKJSNT markoer_kejsersnit Caesarean section 1997-2018
MFRMEDSG markoer_medicinske_sygdomme Medical conditions 1997-2018
MFRMISDA markoer_b_misdannelse Congenital malformation 1997-2018
MFRNVLAN markoer_navlesnorsblod_analyse Umbilical cord blood analysis, with pH/base excess 2003-2018
MFRRUPTU markoer_ruptur Rupture (e.g. uterine) 1997-2018
MFRSMLIN markoer_smertelindring Pain relief 1999-2018
MFRULTRA markoer_ultralyd Ultrasound 1999-2018
MFRVESTM markoer_vestimulation Labour stimulation (oxytocin) 1999-2018
MFRYVEND markoer_ydre_vending External cephalic version 1997-2018

Every row joins to mfr via FK_MFR. Full column-by-column detail for each is in the schema (schema/registers/mfraccre.yaml etc.) and searchable on Find a variable; it is not repeated here as 19 near-identical three-column tables.

MFRDFOED - stillbirth detail, 1997-2018

The richer counterpart to the 19 marker sub-cuts above: a full detail table for the stillbirth subset of mfr’s population (flagged there via LEVENDE_ELLER_DOEDFOEDT), not a marker flag. Joined via FK_MFR, same as the others - not a standalone population, every row here should also have a row in mfr.

DST gives no label or value definition for any column here, the same thinness as MFRHJMFO. Do not confuse this with LPRMFRDF (“Dødfødte ud fra LPR”), a separate DST register deriving stillbirth data from LPR rather than MFR - not modelled in this schema.

Column Type Role Label
FK_MFR character join key
LEVENDE_ELLER_DOEDFOEDT character code
All other columns (17)
Column Type Role Label
CPR_MODER character join key
CPR_FADER character join key
FOEDSELSDATO date date
FOEDSELSKLOKKESLAET character value
KOEN_BARN character code
BARNSNUMMER_FLERFOLDSFOEDSEL numeric value
GESTATIONSALDER_UGER numeric value
GESTATIONSALDER_DAGE_EFTER_UGER numeric value
FOSTERPRAESENTATION character code
VAEGT_BARN numeric value
LAENGDE_BARN numeric value
HOVEDOMFANG numeric value
ABDOMINALOMFANG numeric value
PLACENTAVAEGT numeric value
MISDANNELSER character code
SYGEHUS character code
BEMAERKNING character value
  • CPR_FADER: The father’s CPR-number - a column mfr.yaml and mfrhjmfo.yaml do not carry, specific to this stillbirth-detail table.
  • KOEN_BARN: Value codes not given by DST’s page - not confirmed to share koen or mfr_koen’s encoding.
  • BARNSNUMMER_FLERFOLDSFOEDSEL: The child’s number within a multiple birth, by the variable name - matching mfrhjmfo.yaml’s own BARNSNUMMER_FLERFOLDSFOEDSEL.
  • FOSTERPRAESENTATION: Not confirmed to share mfr_fosterpraesentation.yaml’s DUP/RGAD SKS coding - this register predates the 2019+ restructuring entirely.
  • MISDANNELSER: Congenital malformations, by the variable name - matching mfrhjmfo.yaml’s own MISDANNELSER.
  • SYGEHUS: A hospital identifier, unencoded by name - not confirmed whether this is a SHAK code or something else, DST’s page does not say.
  • BEMAERKNING: A free-text remark field, by the variable name (bemærkning = remark/comment).

No published source gives a data type for 19 of these 19 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: FK_MFR.

Joins to other registers:

  • FK_MFR joins to MFR (one-to-one).
  • CPR_MODER joins to BEF (many-to-one).

Worth knowing:

  • FK_MFR: Foreign key back to mfr.yaml, same pattern as mfrhjmfo.yaml - not confirmed to match mfr’s own cpr_barn specifically.
  • LEVENDE_ELLER_DOEDFOEDT: Present here too even though this register is specifically the stillbirth detail table - presumably always “stillbirth” for every row, but not confirmed as a constant by DST’s documentation.

The Cancer Register

The gold standard for incident cancer diagnoses - more complete and precise for cancer than LPR diagnoses. Running since 1943, which makes it one of the longest continuous cancer registries anywhere. Use it for cancer as an outcome or an exclusion.

It is not a DST register. The Cancer Register is held by Sundhedsdatastyrelsen and does not appear in DST’s register list at all: a project reaches it through Forskerservice, on a separate application. The person key is k_cprnr, not pnr, so rename before joining.

One row per tumour, not per person. Somebody with two primary cancers has two rows, distinguished by k_tumornr. Deduplicating on the person alone collapses second primaries and undercounts incidence.

Column Type Role Label Years
c_icd10 character code ICD10 diagnose 1978 to 2024
c_morfo03 character code ICD3 - Histologi og morfologi 1978 to 2024
c_topo3 character code Tumorens lokalisation 1978 to 2024
d_diagnosedato date date Diagnosedato
k_cprnr character join key CPR-nummer
k_tumornr character code Tumor løbenr.
v_diagnosealder numeric value Patientens alder
All other columns (28)
Column Type Role Label Years
c_amtf07 character code Amtskode 1968 to 2006
c_behandling character code Behandlingskode 1943 to 2003
c_diaggr character code Diagnosegruppering ICD7
c_diaggr_kp character code Diagnosegruppering KP 1978 to 2024
c_diaggr_nordcan character code Diagnosegruppering NordCan
c_grad character code Gradering 1943 to 2008
c_idc7 character code ICD7 diagnose 1943 to 1977
c_komf07 character code Patientens bopælskommune 1968 to 2006
c_kommune character code Bopælskommune 1978 to 2024
c_lateral character code Lateralitet
c_makrogrundlag character code Makroskopisk grundlag
c_mikrogrundlag character code Mikroskopisk grundlag
c_orggr character code ICD7 diagnosegruppering
c_orggr_idc10 character code ICD10 diagnosegruppering 1978 to 2024
c_region character code Patientens bopælsregion 2006 to 2024
c_sarc character code Sarcom. eller ej 1943 to 2006
c_sex character code Patientens køn
c_status character code Patientens status
c_tnm_m character code Angiver fjernmetastaser 2004 to 2024
c_tnm_n character code Angiver lymfeknudemetastaser 2004 to 2024
c_tmn_t character code Størrelse af tumor 2004 to 2024
c_udbred character code Tumorens udbredelse 1943 to 2003
c_udbred_klassifikation character code Anvendt udbredelsesklassifikation
c_aa character code Ann Arbour klassifikation 2004 to 2024
d_fdsdato date date Fødselsdato
d_statdato date date Status dato
v_diagmd numeric value Diagnosemåned
v_diagaar numeric value Diagnoseår
  • c_grad: Only filled in for urinary tract tumours.
  • c_idc7: ICD-7, the coding used before ICD-10. A series running back before 1978 needs both this and c_icd10.
  • c_udbred: Replaced by the TNM columns and Ann Arbor from 2004, when the register moved from paper coding to electronic reporting through LPR. Nothing maps one to the other, so a stage variable across 2004 is two different things.

Join key: k_cprnr.

Joins to other registers:

  • k_cprnr joins to BEF (many-to-one).
Value sets for the coded columns (3)
Code system Values
icd10 Not listed here - see DST’s classification
kom Not listed here - see DST’s classification
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
  • icd10: Do not strip a leading D from these codes. The habit comes from LPR, where the D is really there, and applying it here removes the first character of a real code: E119 becomes 119, which matches nothing and raises no error. The danger is worst where a code genuinely begins with D. ICD-10 chapter D covers in-situ and benign neoplasms, so D46 is myelodysplastic syndrome, a whole code. Strip its “prefix” and you get 46, which looks like a code and is not one.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.

Where these values come from:

Worth knowing:

  • c_icd10: The modern diagnosis code. Older years also carry ICD-7 in c_idc7, so a series running back before ICD-10 has to use both.
  • c_morfo03: Histology and morphology, ICD-O-3. Together with c_topo3 (site) this is what distinguishes tumour types; the ICD-10 code alone does not. M9999X is not an ordinary missing value: the cancer logic sets it as a temporary placeholder when it cannot match a tumour to a confirmed morphology from the Danish Pathology Register, or not within the expected time window of the diagnosis date. It is cleared later by manual review once the real morphology is found. Filtering out only blank/NA values will not catch it.
  • d_diagnosedato: The diagnosis date, which is the incidence date for this register.
  • k_cprnr: The person key. Named k_cprnr rather than pnr, so rename before joining to a DST register.
  • k_tumornr: One person can appear several times: the register counts incident tumours, not people. Deduplicating on the person alone collapses second primaries.
  • v_diagnosealder: Age at diagnosis, precomputed. Recompute from d_fdsdato if your index date differs.

Primary sector - sysi and sssy (Health Insurance Register)

Contacts and services in the primary sector (general practice, practising specialists, physiotherapy etc.). As with LPR, the register is split over time: sysi covers the older years, sssy the newer. Join via pnr. Use it for e.g. GP/specialist contacts, screening or vaccinations billed in primary care. Key fields are named the same in both, but the two registers do not carry an identical column set, so verify with colnames(). They overlap in 2005: both report that year, so reading both without picking a source double-counts it.

No validation studies of this register have ever been published. Coverage is assumed to be high because registration is tied to the provider’s reimbursement, but that is an inference, not a measured validity, and sysi/sssy record almost no clinical information to begin with. Treat diagnoses and reasons for contact with more caution than in registers that do have published validation studies. See Sahl Andersen et al. 2011, The Danish National Health Service Register, Scand J Public Health 39(Suppl 7):34-37.

sysi (1990-2005):

Column Type Role Label
pnr character join key Personal identifier
ydernr character identifier Provider number
speciale character code Specialty, 6-digit
ydlant integer value Number of services under the specialty
afrper character date Settlement period
sikgrup character code Insurance group
year integer date Register year
All other columns (15)
Column Type Role Label Years
ydtyp character code Provider type
ydltid character code Service timing code
ydersamt character code Provider’s county
bruhon numeric value Gross fee to the provider
honuge character date Fee week
barnmak integer code Child marker
pattyp character code Patient type
praktyp character code Practice type
sikrekom character code Municipality of the insured
grdhon character code GRUNDHONORAR 1997 to 2005
henvisni character code Henvisningsydernummer
paragraf character code PARAGRAFRELATION 1997 to 2005
praksiso character code PRAKSISOMRÅDE 1997 to 2005
sikreamt character code Sikredes amt
vagtomr character code VAGTOMRÅDE 1997 to 2005
  • bruhon: In ØRE for 1990-2004 and whole kroner from 2005, so divide the pre-2005 values by 100 before combining them with SSSY. It is the fee the provider received, broadly the public subsidy; the patient’s own co-payment is not included. DST reports that the average fee rose about 10 percent from 2004 to 2005 because general practitioners’ basic and practice fees were spread onto users from 2005, and that this break cannot be removed by cleaning the pre-2005 data.
  • honuge: The week the provider invoiced the county (from 2007, the region) for the service. It is a billing week, not the date of the contact.
  • barnmak: Until 1 January 1996, services provided to a child under 16 were reported under the PARENT’s CPR-number, not the child’s own (Sahl Andersen et al. 2011, Scand J Public Health 39(Suppl 7):34-37, citing Pedersen PA et al., Individual registration of children in the Danish National Health Service Register, Ugeskr Laeger 1999;161:6351-4). This column’s window (1990-2005) straddles that boundary. DST’s own variable list does not explain what barnmak is for, so this is informed context for the practice it likely exists to flag, not a confirmed mechanism: do not assume every child-relevant record before 1996 carries the child’s own CPR-number in this register.

No published source gives a data type for 21 of these 22 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
kom Not listed here - see DST’s classification
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.

Where these values come from:

Worth knowing:

  • ydernr: A provider number, not a person. DST’s variable list does not say what unit it identifies or whether it is stable when a practice changes hands, so do not use it to follow an individual clinician over time without checking that first.
  • speciale: Two codes in one. The first two digits are the provider’s specialty (general practice, dentist and so on); the last four are the type of service. DST publishes no value set for the full code: the service codes come from the collective agreements, and DST points to the historical fee schedules on okportalen.dk. Because the agreements change often, the same service can change code over time, so check a code’s history before comparing years.
  • ydlant: One row can cover several services, so counting rows undercounts activity. Sum this column instead.
  • afrper: DST labels this “Afregningsperiode”, a settlement period rather than a treatment date. Nothing in the variable list says how far settlement can lag the contact, so check the distribution against honuge before using it as a date.
  • sikgrup: Group 1 patients need a referral from their GP to see a specialist, physiotherapist, chiropodist or psychologist, and pay nothing. Group 2 patients may go directly to any GP or specialist, but pay the difference between the fee and the regional subsidy themselves. The two groups therefore leave different traces for the same clinical need, so group membership is a confounder in any analysis of specialist use. Source: borger.dk, “Sygesikring og sikringsgrupper”.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.

sssy (2005-2025):

Column Type Role Label
pnr character join key Personal identifier
ydernr character identifier Provider number
speciale character code Specialty, 6-digit
ydlant numeric value Number of services under the specialty
afrper character date Settlement period
sikgrup character code Insurance group
year integer date Register year
spec2 character code Specialty, 2-digit
All other columns (17)
Column Type Role Label Years
ydtyp character code Provider type
ydltid character code Service timing code
ydersamt character code Provider’s county
bruhon numeric value Gross fee to the provider
honuge character date Fee week
barnmak character code Child marker
kontakt numeric value Contact
patgrp character code Patient group
koenimp character code Sex, imputed values included
alderimp numeric value Alder ultimo inkl. imputerede
behandlingsdato date date 2021 to 2025
cprtjek character code CPR-tjek
cprtype character code CPR-type
registreringstid character code 2021 to 2025
spec80 character code 2021 to 2025
statpop character code 2021 to 2025
version numeric date Version pr. referencetidspunkt for Moduldata
  • bruhon: The fee the provider received, which is broadly the public health insurance subsidy. The patient’s own co-payment is NOT included, and group 2 patients and several specialties (dentists, for example) pay part of the fee themselves, so this is public expenditure, not the total cost. In whole kroner from 2005 (SYSI before 2005 is in øre). From 2005 the general practitioners’ basic and practice fees, paid per listed patient whether or not the patient attended, are spread over the people who did receive GP services. DST reports that this raised the average fee by about 10 percent from 2004 to 2005, and that the break cannot be removed by cleaning the pre-2005 data.
  • honuge: The week the provider invoiced the region (before 2007, the county) for the service. It is a billing week, not the date of the contact.
  • kontakt: 0 if the service is not a contact, otherwise equal to ydlant. DST counts as contacts the services that involve direct contact between patient and provider: consultations (including phone and e-mail), home visits and the like. How contacts are defined has changed over time, and for physiotherapy and psychology DST calls the count uncertain, so read trends with that in mind. Not in SYSI; SYST has a contact count for 1992-2005, but do not assume it is comparable across the 2005 boundary.
  • koenimp: Imputed where the source was missing, so it is not identical to koen in BEF. Prefer BEF when you need sex as a study variable.
  • behandlingsdato: Only from 2021, and DST publishes neither a label nor a description for it. The name suggests a treatment date, but that is a reading of the name. Before 2021 the register has no contact date at all, only honuge and afrper, which are billing periods.

No published source gives a data type for 6 of these 25 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
koen 1 Mand, 2 Kvinde, 9 Uoplyst
  • koen: DST’s classification KOEN_V1_1980 also defines 9 for not stated, which a delivery may not contain but a value set should. Sex is taken from the tenth digit of the CPR number: even is female, odd is male.

Where these values come from:

Worth knowing:

  • ydernr: A provider number, not a person. DST’s variable list does not say what unit it identifies or whether it is stable when a practice changes hands, so do not use it to follow an individual clinician over time without checking that first.
  • speciale: Two codes in one. The first two digits are the provider’s specialty (general practice, dentist and so on, the same as spec2); the last four are the type of service. DST publishes no value set for the full code: the service codes come from the collective agreements, and DST points to the historical fee schedules on okportalen.dk. Because the agreements change often, the same service can change code over time, so check a code’s history before comparing years.
  • ydlant: One row can cover several services, so counting rows undercounts activity. Sum this column instead.
  • afrper: DST labels this “Afregningsperiode”, a settlement period rather than a treatment date. Nothing in the variable list says how far settlement can lag the contact, so check the distribution against honuge before using it as a date.
  • sikgrup: Group 1 patients need a referral from their GP to see a specialist, physiotherapist, chiropodist or psychologist, and pay nothing. Group 2 patients may go directly to any GP or specialist, but pay the difference between the fee and the regional subsidy themselves. The two groups therefore leave different traces for the same clinical need, so group membership is a confounder in any analysis of specialist use. Source: borger.dk, “Sygesikring og sikringsgrupper”.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.
  • spec2: The first two digits of speciale: the kind of provider (general practice, ear-nose-throat specialist, dentist, psychologist, laboratory and so on). This is the column to filter on when you want only general practice and practising specialists, because the register also covers dentists, physiotherapists, chiropractors and others. General practice is spread over several codes (daytime, evening and phone consultations have codes of their own), so take the list from DST’s value set rather than picking a single code.

Laboratory results - Laboratoriedatabasens Forskertabel

Laboratory and blood test results: HbA1c, lipids, creatinine. A very large register, well over a billion rows, so filter with arrow or duckplyr before you collect() into R.

It is not a DST register. This is Laboratoriedatabasens Forskertabel (LAB_F), held by Sundhedsdatastyrelsen and reached through Forskerservice. It is not in DST’s register list. The exact table name can still differ by project: lab_forsker and laboratorieproevesvar are narrower cuts of the same delivery as lab_dm_forsker (fewer columns, some renamed - see the reader notes on the columns below for the exact differences), not separate registers. In the clinical epidemiology literature it is usually called RLRR, Register of Laboratory Results for Research (see e.g. Arendt et al. 2020, Clinical Epidemiology 12:469-475). The columns are named in English: patient_cpr, analysiscode, samplingdate, value, unit. NPU is the coding system used in analysiscode, not a column name.

Sundhedsdatastyrelsen updated the laboratory delivery on 3 October 2025 (announcement →): “Det nye LAB erstatter den tidligere version af LAB.” The announcement names four tables - laboratorieproevesvar, Dimlaboratoriekoder, DimNPU and Proevesvar_optaelling - but never mentions lab_dm_forsker by name, and does not say what happens to projects already using it. The official data dictionary this page and the schema are built from (PDF) is Version 4, dated 1 December 2023 - nearly two years before this announcement - and documents lab_dm_forsker only. So lab_dm_forsker is not a new “common data model” superseding the older tables; if anything the evidence points the other way, with laboratorieproevesvar being the one that just got new companion tables. Whether lab_dm_forsker is being retired, and what laboratorieproevesvar’s real columns are after the October 2025 change, is not resolved here - check the order sheet (“bestillingsark”) on Sundhedsdatastyrelsen’s site, or your own delivery, before relying on either name. If you have insights into this issue, please fell free to use the feedback box to the right.

value is text, not a number. Alongside numeric results it holds a fixed set of words - POSITIV, NEGATIV, IKKE PÅVIST, INGEN VÆKST and the blood type codes. as.numeric() turns every one of them into NA without warning, which drops exactly the samples where something was found.

Coverage starts in 2008, not the 1990s, and complete coverage arrives per laboratory between 2010 and 2016. Only NPU- and DNK-coded results reach the table, about 95 per cent; results with a laboratory’s own local code are absent, as are patients who declined consent. See Laboratoriedatabasen →.

Need data from before 2008? Arendt et al. 2020 describes a separate regional database, LABKA (held by Aarhus University Hospital’s Department of Clinical Epidemiology, not DST or Forskerservice), with coverage back to 1997 in two regions. It is not documented on this page: neither Arendt et al. 2020 nor Grann et al. 2011, the original LABKA paper, gives literal column names, only prose descriptions of what the database holds, so there is nothing here to check a real delivery against. If you have LABKA access, contact the Department of Clinical Epidemiology directly for the actual variable list.

DARTER: a dedicated extraction guide for laboratorieproevesvar_ is in progress - see DARTER - Register paths and datastores.

Healthcare costs (under development)

Under development - confirm everything in your own delivery. This section describes cost sources at the register level. Exact table and column names and the available years change from year to year (the DRG rate system is updated annually) and are not verified here. Use it as a pointer, and clarify the specific files with your data manager.

To compute healthcare use/costs per person, they are typically assembled from several sources:

  • Somatic hospital contacts: DRG-grouped rates from the Danish Health Data Authority (DRG = inpatient, DAG = outpatient). Rates express average operating expenses per DRG group and are computed annually - see SDS DRG rates.
  • Psychiatric hospital contacts: are not billed by DRG. The main principle is a bed-day rate for inpatients and a visit rate for outpatients - keep somatic and psychiatric separate.
  • Primary sector (general practice, specialists etc.): fees in sysi/sssy (see the section above).
  • Medication: patient co-payment vs. reimbursement in LMDB (section 7).

Availability of cost data varies (some years/sources are missing, e.g. more recent DRG years). The pattern is inspired by the Plana-Ripoll group’s code on OSF, but the variable names there are from a 2022 delivery and should not be assumed current.

7. LMDB - Prescription Register

Owned by the Danish Health Data Authority as the Prescription Register: Lægemiddelstatistikregisteret →.

One row per dispensed prescription. Covers approximately 1994 onwards.

Column Type Role Label Years
pnr character join key Personal identifier 1995-Q2 to 2025-Q2
eksd date date Dispensing date 1995-Q2 to 2025-Q2
atc character code ATC code, full 7 characters 1995-Q2 to 2025-Q2
atc1 character code ATC level 1 (1 character) 1995-Q2 to 2025-Q2
atc2 character code ATC level 2 (3 characters) 1995-Q2 to 2025-Q2
atc3 character code ATC level 3 (4 characters) 1995-Q2 to 2025-Q2
atc4 character code ATC level 4 (5 characters) 1995-Q2 to 2025-Q2
vnr character code Item number (product key) 1995-Q2 to 2025-Q2
apk numeric value Number of packages 1995-Q2 to 2025-Q2
year integer date Dispensing year
All other columns (55)
Column Type Role Label Years
indo character code Indication code 2004-Q2 to 2025-Q2
packsize numeric value Package size 1995-Q2 to 2025-Q2
strnum numeric value Strength, numeric 1995-Q2 to 2025-Q2
strunit character value Unit for the numeric strength 1995-Q2 to 2025-Q2
aldr numeric value Age at dispensing 1995 to 2025
abc character code ABC code (price rank within substitution group) 2007 to 2025
aip numeric value Pharmacy purchase price per package 1995 to 2025
aref character code Other reimbursement schemes 1995 to 2025
aup numeric value Pharmacy retail price per package 1995 to 2025
bald character code Child’s age (code) 1995 to 2011
cprtjek character code CPR check 1995 to 2025
cprtype character code CPR type 1995 to 2025
cpr_kom character code Municipality of residence (CPR) on the dispensing date 2005 to 2025
cpr_reg character code Region of residence (CPR) on the dispensing date 2005 to 2025
dosform character code Pharmaceutical form 1995 to 2025
doso character code Dosage code 2004 to 2025
edbl character code 2020 to 2025
ejs character code Substitution opted out 1997 to 2025
eksp numeric value Total price of the dispensing 1995 to 2025
ekst character code Dispensing type 1995 to 2025
etid numeric date Dispensing time 1997 to 2025
ibgp numeric value Reported subsidy calculation price 2000 to 2025
ibnr character code Reporter number 1995 to 2025
itype character code Reporter type 1995 to 2025
kom character code Municipality code (paying municipality) 1995 to 2025
korr character code Correction code 1995 to 2025
name character code Product name 1995 to 2025
ovnr character code Prescribed item number 1997 to 2025
packtext character code Package text 1995 to 2025
patt character code Patient type 2000 to 2025
pksubgr character code Package substitution group 2007 to 2025
pnr12 character join key CPR number 1995 to 2025
pprs character code Dispensing restriction 1995 to 2025
ptp character code Patient payment 1995 to 2025
ramt character code County/region code (paying authority) 1995 to 2025
reca character code Authorisation code of the prescriber 2005 to 2025
recu character code Prescriber 1995 to 2025
rgl1 character code Municipal rule number 1 1995 to 2025
rgl2 character code Municipal rule number 2 1995 to 2025
rgla character code Regional subsidy rule number 1995 to 2025
rimb character code Subsidy code 1995 to 2025
rinr character code Repeat (reiteration) number 1995 to 2025
sektor character code Sector 1995 to 2025
streng character code Strength, plain text 1995 to 2025
takd date date Tariff date 1995 to 2025
tard date date Pricing date 2000 to 2025
tilpris numeric value Subsidy price per package 1995 to 2025
tsk1 character code Municipal subsidy 1 1995 to 2025
tsk2 character code Municipal subsidy 2 1995 to 2025
tsk3 character code Other subsidies 1995 to 2025
tska character code Regional medicine subsidy 1995 to 2025
udlv character code Place of dispensing 1995 to 2025
voltypecode character code 1995 to 2025
voltypetxt character code 1995 to 2025
volume character code Volume (unit given by voltypecode) 1995 to 2025
  • indo: Recorded only when the prescriber picks an indication from the drop-down. Typed as free text it is not carried over, so the column is often empty.
  • aldr: In 1994-1995 a few ages look like ranges (for example 0-3): a future CPR number was reported, giving a negative age, and those rows should be ignored. Where bald is filled, this is the parent’s age, not the child’s.
  • aup: The price of one package at the time of pricing (tard): the purchase price (aip) plus the pharmacy margin plus VAT. It excludes the prescription fee, and the margin formula changes regularly.
  • bald: Used until March 2011 when a medicine for someone under 18 was registered on a parent’s or a substitute CPR number. When it is filled, pnr, sex and age belong to the parent. Children got their own health insurance card from 1 January 1996, but the change was only nearly complete by summer 1996, so before that children’s use is undercounted and young women’s (usually the mother’s) overcounted.
  • cpr_kom: Filled only from January 2005. The patient’s municipality of residence from CPR at the time of purchase; use this, not kom, for where the patient lived.
  • cpr_reg: Filled only from January 2005. The patient’s region of residence from CPR at the time of purchase; use this, not ramt, for where the patient lived.
  • doso: Introduced 1 April 2004, and some prescribing systems only from 1 April 2005. A dose written as free text gets no code; in 2012 about 57 percent of prescriptions had one.
  • ejs: The substitution rules changed in 1997 (in this register from October 1997) and were simplified in June 2001, so the meaning of an empty field differs across those dates.
  • eksp: Total price in kroner including VAT; for a prescription at a community pharmacy it is (aup + prescription fee) times the number of packages. Hospital pharmacies used internal settlement prices until 2011 and the last registered purchase price from 2011, so hospital data are not comparable across 2011, and turnover from community and hospital pharmacies cannot be compared at all.
  • ekst: Sundhedsdatastyrelsen advises against selecting data on this field alone, because the types were not always used correctly (in 1994, for example, some prescriptions were reported as over-the-counter sales).
  • etid: Introduced October 1997. Only from March 2000 was it required to be the time the medicine was handed over; before that it is unknown which time was reported, and some pharmacies are suspected of still reporting the pricing time.
  • ibgp: In kroner including VAT. Some pharmacies left it empty for patients entitled to a subsidy who were still paying in full; corrected from 2003.
  • kom: The municipality that paid a municipal subsidy, not where the patient lived: use cpr_kom for residence. Municipality codes change at the 2007 reform.
  • korr: 1 marks a correction (a reversal, with negative apk, volume or eksp), 0 a normal row. Until 1996 a value 2 also existed and has been recoded to 1. One hospital pharmacy reported corrections with positive counts until January 2005, so it shows no corrections before then and its total price is overestimated.
  • patt: Introduced with the needs-based subsidy system on 1 March 2000. Some pharmacies left it empty for patients entitled to a subsidy who were still paying in full; corrected from 2003.
  • ptp: The patient’s payment in kroner including VAT, normally eksp minus tska, tsk1 and tsk2. A few rows do not add up.
  • ramt: The region (until 2006, the county) that paid the subsidy, not where the patient lived: use cpr_reg for residence.
  • rgla: New rule codes came in on 1 March 2000 and some pharmacies kept using the old ones for a while. Before March 2000, 00 meant that a subsidy was paid, but some pharmacies used 00 as a default on every row until December 2000.
  • rinr: Sundhedsdatastyrelsen says not to rely much on this field, especially for paper prescriptions: several pharmacy systems misused codes 00 and 01 until 2003.
  • tard: The date the price and subsidy price were set, introduced with the subsidy system in March 2000. It can differ from eksd, the date the medicine was handed over: in January-September 2012, 83 percent of prescriptions had the two dates equal.
  • tska: The regional medicine subsidy in kroner including VAT. Pharmacies give the regions a 1.72 percent discount (excluding VAT), so Sundhedsdatastyrelsen says to multiply by 0.98624 to get the regions’ actual expense. Should be 0 for subsidy-eligible purchases below the subsidy threshold, but is not always.

No published source gives a data type for 28 of these 65 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (3)
Code system Values
atc Not listed here - see DST’s classification
kom Not listed here - see DST’s classification
reg 0 Uoplyst, 81 Nordjylland, 82 Midtjylland, 83 Syddanmark, 84 Hovedstaden, 85 Sjælland
  • atc: As a rule, filter on the full 7-character code rather than on the level columns: atc2 holds three characters, so a longer pattern matched against it can never match, and it returns nothing at all with no error. The level columns are well suited to grouping, and to filtering when every code you want is the same length as the column.
  • kom: These codes are valid from 1 January 2007. A study reaching further back needs the pre-reform classification, where the same number can mean a different municipality - confirmed for two reused codes against a current-only DST source: 707 is Norddjurs today, not its pre-2007 meaning, and likewise 849 is Jammerbugt. lookup: below covers only this post-2007 set (99 entries), not the full 278-code values_from file. Christiansø (411) is included in lookup: even though it is not a municipality (see description above): it is a real value a kom column can hold, and DST’s own current-only classification lists it as its own area code alongside the 98 municipalities. Excluding it would just move the “unhandled code” problem this fix is meant to solve onto that one value.
  • reg: Do not confuse these with AMT, the pre-2007 counties, which has 16 codes in the ranges 11-14, 21-24, 31-37 and 88. Different geography, different era.

Where these values come from:

Worth knowing:

  • pnr: DST’s variable list calls this column PNR12. Check whether your variable is named pnr or pnr12. Do not confuse this with the pnr documented on esundhed’s page for this register (DocumentationExtended?id=14): that pnr is the pharmacy or manufacturer’s production-unit number, length 10, not a person. Same name, unrelated variable, on the two pages that between them cover this register. Before 1996, a child’s prescriptions were filed under the mother’s pnr, not the child’s own - community pharmacies only switched to issuing prescriptions under the child’s own name from 1996 onward (Pottegård et al. 2017, doi:10.1093/ije/dyw213). Filtering this register by a child’s own pnr for exposure before 1996 silently misses those rows: they are not absent, they are attributed to a different person entirely.
  • eksd: The date the prescription was collected at the pharmacy. Not the date it was prescribed, and not evidence that the medicine was taken.
  • atc: The newest ATC code for the product is always attached, also to earlier years. A count made some years ago can therefore differ from a new one if a product’s code has changed since.
  • vnr: The only reliable way to isolate one specific product. Two brands with the same active substance share an ATC code but have different item numbers.
  • apk: Hospital pharmacies can report decimals, everyone else whole numbers. Blank for hospital-pharmacy parenteral service products in ATC groups J01 and L01 from 2011. For dose-dispensed medicine (ekst DD) units are reported rather than packages, and before 2007 some of those units were wrongly read as whole packages.
  • year: Not a DST variable. It comes from fastreg’s parquet conversion, which concatenates the yearly deliveries, so it exists in the data you read but not in DST’s own documentation of this register.
All confirmed columns in LMDB

pnr, eksd, ekst, atc, atc1, atc2, atc3, atc4, indo, vnr, apk, aldr, bald, eksp, korr, rinr, name, streng, packtext, volume, voltypecode, voltypetxt, dosform, strnum, strunit, packsize, cprtjek, cprtype, year, etid, ovnr, patt, doso, reca, abc

Filtering on atc2 fails silently. The level columns are shorter than the full code: atc2 holds three characters, so grepl("N02A", atc2) matches nothing and returns zero rows without an error. Filter on atc and keep the level columns for grouping. Details, and a check you can run on your own extract, are in Medication (ATC).

Data quality of indo and doso

indo (indication code) is recorded only when the doctor picks an indication from the drop-down menu in the electronic prescription; typed as free text, it is not carried over. It is therefore missing on about 12-18% of prescriptions (more before 1 October 2017) and is often nonspecific. The dosage field doso is effectively empty (recorded for ~0.06% of prescriptions). See Medication (ATC) for how to handle this.

8. Socioeconomic registers

All three registers are used for SEP extraction following SEPLINE guidelines (Hjorth et al. 2025). No single combined SEP variable is calculated - three separate dimensions.

UDDA - Education Register

One record per person per year - updated when the education level changes.

Column Type Role Label Years
pnr character join key Personal identifier 1980 to 2025
hfaudd character code Highest completed education 1980 to 2025
udd character code Education code 1980 to 2025
hf_vfra date date Date the education was completed 1980 to 2025
year integer date Register year
All other columns (13)
Column Type Role Label Years
hf_kilde character code Source of the education record 1980 to 2025
hfinstnr character code Institution that awarded the education 1980 to 2025
almaudd character code Highest completed general education 1980 to 2025
erhaudd character code Highest completed vocational education 1980 to 2025
alm_vfra date date Date the general education was obtained 1980 to 2025
erh_vfra date date Date the vocational education was obtained 1980 to 2025
ig_vfra date date Start date of the ongoing education 1980 to 2025
alminstnr character code Institution, general education 1980 to 2025
erhinstnr character code Institution, vocational education 1980 to 2025
iginstnr character code Institution, ongoing education 1980 to 2025
cprtjek character code CPR check 2005 to 2025
cprtype character code CPR type 2005 to 2025
version character code Module data version 2005 to 2025
  • hfinstnr: The guide previously referred to this column as INSTNR. DST’s list has no INSTNR; the institution columns are HFINSTNR, ALMINSTNR, ERHINSTNR and IGINSTNR, one per kind of education.
  • almaudd: The general-education track only. hfaudd is the highest completed education of any kind, so the two answer different questions and are not interchangeable.
  • ig_vfra: Pairs with udd: this is when the ongoing education began. An education with a start and no completion is either still running or was interrupted, and the register does not distinguish the two.

No published source gives a data type for 17 of these 18 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (1)
Code system Values
hfaudd Not listed here - see DST’s classification
  • hfaudd: This is an identifier, not a scale. The level (short, medium, long) has to be looked up in a separate table, and cannot be read off the digits: 4112 is an electrician, and taking the first two digits as a level code makes it a long higher education. DST documents the ongoing-education codes separately as DISCED-15 UDD.

Where these values come from:

Worth knowing:

  • hfaudd: A code for which education, not for its level. UDDA carries no level column at all, so the level has to come from a lookup table.
  • udd: Not the same code system as hfaudd. Under DISCED-15, AUDD codes describe a completed education and UDD codes one that is ongoing or was interrupted, so a lookup table built for one will not fit the other.
  • year: Not a DST variable. It is the partition the yearly deliveries were written into, so filtering on it stops the other years being read at all. Use it to limit how much is read, not to decide when something happened: for that, use the register’s own date column.
Importanthfaudd is not an education level - do not read the digits

This is the single easiest mistake to make with UDDA, and it produces wrong numbers without any error message. There are two different code systems, and they look confusingly alike:

What it identifies Example
Education code (hfaudd) Which education, as a four-digit DISCED-15 code 4272 = electrician
Level code How long/high the education is, two digits 30 = vocational, 70 = master’s

hfaudd is an identifier, not a scale. The first two digits are simply the start of a serial number, and there is no arithmetic relationship between the two systems. Taking substr(hfaudd, 1, 2) and treating it as the level is wrong, and it fails in both directions:

  • hfaudd = 4272 is an electrician - vocational, level 30. Reading 42 and comparing it to 40 makes it a long higher education.
  • hfaudd = 0141 is genuinely level 40, short cycle higher education. Reading 01 (or 14, if the column is numeric and the leading zero is gone) matches no level at all, so a real education becomes missing data.

UDDA does not contain the level. DST’s education register holds only HFAUDD, HF_KILDE, HF_VFRA, HF_VTIL and INSTNR - there is no level column to read. The level has to come from a lookup table that maps each education code to its level. See Socioeconomic variables for how to do it.

How often the substr() shortcut is actually wrong

Tested against the full DISCED-15 list, the rule gets 58% of the 4,621 codes right, and 1,149 of them land in a confidently wrong category rather than in “unknown”. So it is not a rule that fails loudly on odd cases: it is right often enough to look like it works, and wrong often enough to move real numbers.

It looks plausible because the level codes (10, 15, 20, 30, 40, 70, 90) have the same shape as the first two digits of an education code. That resemblance is a coincidence of how the serial numbers were assigned, not a mapping.

AUDD or UDD - pick the right lookup. DISCED-15 has one code for an education that is ongoing or interrupted (UDD) and one for a completed education (AUDD), and DST publishes format tables for both. hfaudd is højest fuldførte AUDD, the highest completed education, so an audd lookup is the one that fits. A udd table will still join - it will just match some rows, miss others, and never tell you. Naming and paths are in Format tables.

FAIK - Family Income

Household-equivalised disposable income per year. Link: join BEF (pnr, familie_id, year) with FAIK (familie_id, year).

The structure can differ from DST’s documentation. DST documents FAIK with no pnr, but in the DARTER delivery FAIK from 2022 onward also carries pnr, and the family’s row is repeated once per family member instead of appearing once. Joining on familie_id alone then multiplies your rows silently. Check your own delivery before you rely on the join - how, and what to do about it, is in Socioeconomic variables.

Column Type Role Label Years
pnr character join key Personal identifier
familie_id character join key Household key
famaekvivadisp_13 numeric value Household-equivalised disposable income
year integer date Register year
famdisponibel_13 numeric value Disposable income
famindkomstialt_13 numeric value Total income before taxes
famsociogrup_13 numeric code Socioeconomic group, 2013 definition 1993 to 2024
famtype numeric code Family type
All other columns (79)
Column Type Role Label Years
famaekvivadisp numeric value Equivalised disposable family income 1990 to 2012
famaekvivaindknetto numeric value Equivalised total income including net interest 1990 to 2012
famaktieindk numeric value Share income 1990 to 2009
famandenpension numeric value Other pension payments to the family
famandoverforsel numeric value Other transfers to the family 1990 to 2012
famantalfskattepligtige numeric value Number of fully taxable adults in the family
famarbejdsloesp numeric value Unemployment benefit and training allowance
famarbmabidrag numeric value Labour market contributions
famboernetilskud numeric value Child benefit and family allowances
famboligform numeric code Housing tenure 2000 to 2024
famboligstoette numeric value Housing benefit paid to the family
famboligtype numeric code Dwelling type 2000 to 2024
fambruttoindk numeric value Gross family income 1990 to 2009
famdagpenge_kontant_13 numeric value Total benefits and social assistance
famdisponibel numeric value Disposable family income 1990 to 2012
famefterloen numeric value Early retirement pay
famejdskat_ejerbolig numeric value Property tax, homeowners 2010 to 2024
famejdskat_lejerbolig numeric value Property tax, tenants 2010 to 2024
famejendomsvurdering numeric value Cash property value
famerhvervsindk numeric value Business income for the family 1990 to 2012
famerhvervsindk_13 numeric value Business income: wages and net profit
famfolkefortid_13 numeric value State and early retirement pension in the family
famformrest_ny05 numeric value Net residual wealth at year end
famformueaktiver numeric value Total assets
famformueindk numeric value Total capital income for the family 1990 to 2012
famformueindk_brutto numeric value Capital income, gross
famfradragialt numeric value Total calculated deductions 1990 to 2012
famfrynsegoder numeric value Taxable value of fringe benefits 1993 to 2009
famgaeldialt numeric value Liabilities
famgron_check numeric value Green check 2010 to 2024
famhoejstudda character code Highest education among the adults 2000 to 2024
famhonny numeric value Fees liable to labour market contributions
famindkomstialt numeric value Total family income before tax 1990 to 2012
famkontanthjaelp numeric value Social assistance for the family 1990 to 2009
famkontanthjaelp_13 numeric value Social assistance in the family
famlejevaerdi numeric value Imputed rental value of owner-occupied dwelling 1990 to 2012
famlejev_egen_bolig numeric value Imputed rental value of owner-occupied dwelling
famloenmv numeric value Total wage income in the family 1990 to 2012
famloenmv_13 numeric value Total wage income in the family
fammidlertidyd numeric value Temporary transfer incomes 1990 to 2012
famoevrigformue numeric value Other capital income for the family 1990 to 2009
famoevrigformue_13 numeric value Other capital incomes in the family
famoffpens_eftlon_13 numeric value Public pensions in the family
famoff_overforsel_13 numeric value Public transfers to the family
famorlovsydelse numeric value Leave benefits paid to the family 1994 to 2009
famoverfoerindk numeric value Total transfer incomes 1990 to 2012
famovergangyd numeric value Total transitional allowance 1994 to 2006
famovrig_dagpenge_akas_13 numeric value Other benefits from unemployment funds
famovrig_kontanthjalp_13 numeric value Activation, unemployment and rehabilitation allowance
famovrig_overforsel_13 numeric value Other transfer incomes in the family
fampensionatp numeric value ATP pension payments
fampensionialt numeric value Total pensions for the family 1990 to 2012
fampensoffentlig numeric value State and early retirement pension 1990 to 2009
fampenstjeneste numeric value Civil servant pension
famprivat_pension_13 numeric value Private pensions in the family
famrenteindk numeric value Total interest income from Denmark 1990 to 2009
famrenteindk_13 numeric value Total taxable interest income
famrenteudgifter numeric value Total deductible interest expenses 1990 to 2012
famrenteudgifter_13 numeric value Interest expenses
famrestbistandsyd numeric value Other benefits from municipalities and unemployment funds 1990 to 2009
famrestindk numeric value Miscellaneous unclassified income 1990 to 2012
famrestindk_13 numeric value Other personal income in the family
famsamletindk numeric value Total income for the family 1990 to 2009
famskatfriyd numeric value Tax-free incomes in the family 1990 to 2012
famskatmvialt numeric value Tax and labour market contributions paid 1990 to 2012
famskatmvialt_13 numeric value Tax, labour market contributions and special pension
famskatpligtindk numeric value Taxable income for the family
famskattot numeric value Total income tax paid 1990 to 2009
famskattot_13 numeric value Total personal final tax
famsociogrup numeric code Socioeconomic group 1994 to 2009
famsu numeric value State education grants (SU)
famsumindknettorent numeric value Total income including net interest 1990 to 2012
famsyg_barsel_13 numeric value Sickness and maternity benefits
famtransportfradrag numeric value Total commuting deduction 1990 to 2009
famunderhbidrag numeric value Maintenance payments made by the family
famvirkordind numeric value Amounts placed in the business tax schemes
famvirkoverskud numeric value Net profit from self-employment 1990 to 2009
famvirkoverskud_13 numeric value Total profit from self-employment
version numeric code Module data version
  • famaekvivadisp: The same weighting scheme as FAMAEKVIVADISP_13 below, just algebraically rearranged on the source page: the first adult over 14 counts as 1.0, each further person over 14 as 0.5, and each child under 15 as 0.3. All persons belonging to the same family on 31 December of the income year (same E-familienummer), including resident children under 25, are assigned the family’s equivalised income. FAMDISPONIBEL is the same money before that division.
  • famandoverforsel: DST flags a data break both within this variable and across variables, and discontinued it in 2013. It sums housing benefit, child benefit and student grants, each of which changed rules over the period (child benefit rates, for example), so year-to-year changes can be rule changes rather than real ones.
  • famdisponibel: DST flags a data break within this variable. It was discontinued in 2013 and replaced by famdisponibel_13, which runs 1987-2024 on one definition; use that for any time series. The main changes in this old series: labour market contribution introduced in 1994, imputed rental value of owner-occupied homes calculated differently from 1994 and again from 2007, and tax-free social assistance and heating aid included from 2002.
  • famerhvervsindk: DST flags a data break both within this variable and across variables. It was discontinued in 2013 and replaced by famerhvervsindk_13, which also includes business interest, so the two are not the same quantity. In this old series, fees subject to labour market contribution are included from 1994, and wages of foreign researchers under the researcher tax scheme are included only in 2002-2003 and from 2008.
  • famformueindk: DST flags a data break within this variable. It was discontinued in 2013 and replaced by famformueindk_brutto, which leaves out the imputed rental value of the family’s own home, so the two are not the same quantity. Changes in this old series: share income taxed separately from 1991, rental income from letting a holiday home or the family’s home included from 1993, the rental value rule changed in 1994, and gains from selling property included from 1996.
  • famfradragialt: DST flags a data break within this variable, because the deductions it sums follow the tax rules of each year. For example, the deduction for changing workplaces moved to famtransportfradrag in 1994, early-retirement contributions entered in 1999 and the employment deduction was introduced in 2004.
  • famindkomstialt: DST flags a data break within this variable. It was discontinued in 2013 and replaced by famindkomstialt_13; use that for any time series. Changes in this old series include: rehabilitation benefit made taxable (and so larger) from October 1990, share income not always included in 1991-2000, and wages of people under the researcher tax scheme left out in 1992-2001 and 2004-2007, partly included in 2002-2003 and fully included from 2008.
  • famlejevaerdi: DST flags a data break both within this variable and across variables, and discontinued it in 2013; famlejev_egen_bolig replaces it. The rule changed in 1994: until 1993 every home and holiday home a person owned counted, and from 1994 at most one home and one holiday home, prorated when owned for part of the year. The underlying calculation changed again in 2007.
  • famloenmv: DST flags a data break both within this variable and across variables, and discontinued it in 2013 (famloenmv_13 is the current series). Group life insurance through an employer pension is included from 1993 (before that it sits in famrestindk), and from 1994 wages come mainly from the final tax assessment rather than from employers’ information slips.
  • fammidlertidyd: DST flags a data break both within this variable and across variables, and discontinued it in 2013. Rehabilitation benefit was made taxable (and so larger) from October 1990, and leave benefits were introduced in 1992 (in famrestindk for 1992-1993) and ended in 2011.
  • famoverfoerindk: DST flags a data break both within this variable and across variables, and discontinued it in 2013. It sums pensions, temporary benefits and other transfers, so it inherits every change in those: for example rehabilitation benefit made taxable from October 1990 and civil-service pensions included only from 1991.
  • fampensionialt: DST flags a data break both within this variable and across variables, and discontinued it in 2013. Civil-service, labour-market and private pensions are formed for the first time in 1991 (before that they sit in famrestindk). In 2008 flex benefit is included here but not in famefterloen, so adding up the sub-variables for 2008 misses that amount.
  • famrestindk: DST flags a data break both within this variable and across variables. It is a catch-all for income that fits nowhere else, and its content has shifted: several items (fringe benefits, group life insurance, foreign business profit) are only in it until 1993 or 1994 before moving to their own variables, and from 2002 it includes a tax-free part of child support that DST models rather than observes.
  • famskatfriyd: DST flags a data break both within this variable and across variables. Most social assistance was made taxable in 1994 and left this variable, which drops as a result; the small part that stayed tax-free is not included in 1994-2001. The tax-free part of child support is included from 2002.
  • famskatmvialt: DST flags a data break within this variable (famskatmvialt_13 is the current series). Taxes follow each year’s tax system: labour market contribution is included from 1994, the special pension contribution in 1998-2003, county tax until 2006 and the health contribution from 2007, and wealth tax only before 1997.
  • famsumindknettorent: DST flags a data break within this variable. It has the same changes as famindkomstialt: rehabilitation benefit made taxable from October 1990, share income not always included in 1991-2000, and wages under the researcher tax scheme left out in 1992-2001 and 2004-2007.
  • famvirkoverskud: Discontinued in 2013 and replaced by famvirkoverskud_13, which is the net profit after interest in the business, so the two are not the same quantity.

No published source gives a data type for 67 of these 87 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: familie_id.

Joins to other registers:

  • familie_id joins to BEF (one-to-many).
Value sets for the coded columns (3)
Code system Values
famboligform 1 Ejerbolig, 2 Lejebolig, 9 Uoplyst
socio13 11 Selvstændige, 110 Selvstændige, 111 Selvstændige erhvervsdrivende med 10 eller flere ansatte, 112 Selvstændige erhvervsdrivende med 5-9 ansatte, 113 Selvstændige erhvervsdrivende med 1-4 ansatte, 114 Selvstændige erhvervsdrivende uden ansatte, 12 Medarbejdende ægtefælle, 120 Medarbejdende ægtefælle, 13 Lønmodtagere, 131 Lønmodtagere med ledelsesarbejde, 132 Lønmodtager i arbejde der forudsætter færdigheder på højeste niveau, 133 Lønmodtager i arbejde der forudsætter færdigheder på mellemniveau, 134 Lønmodtager i arbejde der forudsætter færdigheder på grundniveau, 135 Andre lønmodtagere, 139 Lønmodtager uden nærmere angivelse, 21 Arbejdsløs mindst halvdelen af året, 210 Arbejdsløse mindst halvdelen af året, 22 Sygedagpenge, orlov mv., 220 Modtager af sygedagpenge, uddannelsesgodtgørelse, orlovsydelser mv., 31 Uddannelsessøgende, 310 Under uddannelse, inkl. skoleelever på min. 15 år, 32 Pensionist/efterløn, 321 Førtidspensionister, 322 Folkepensionister, 323 Efterlønsmodtagere mv., 33 Kontanthjælp, 330 Kontanthjælpsmodtagere, 41 Andre, 410 Andre, 42 Børn, 420 Børn under 15 år, ultimo året
famtype 0 Ingen oplysninger, 1 Ægtepar forskelligt køn, 2 Registreret partnerskab, 3 Samlevende par, 4 Samboende par, 6 Enlig mænd (herunder også ikke hjemmeboende børn), 7 Enlig kvinder (herunder også ikke hjemmeboende børn), 8 Ægtepar samme køn
  • socio13: Two codes are easy to misread. 410 is Andre (other), not unemployed: the unemployed are 210. And 420 is children under 15, a known category rather than a missing value, so it appearing in an adult cohort means the index date is wrong rather than the data being incomplete.
  • famtype: There is no code 5. The sequence runs 0 to 4 and then 6 to 8, which is easy to read as a missing value rather than as a code that never existed.

Where these values come from:

How it is computed:

famaekvivadisp_13

FAMAEKVIVADISP_13 = FAMDISPONIBEL_13 / (1 + (0.5 * (number of people over 14 in the family - 1)) + (0.3 * number of people under 15 in the family))

famaekvivadisp

FAMAEKVIVADISP = FAMDISPONIBEL / (0.5 + (0.5 * number of people over 14 in the family) + (0.3 * number of people under 15 in the family))

famaekvivaindknetto

FAMAEKVIVAINDKNETTO = FAMSUMINDKNETTORENT / (0.5 + (0.5 * number of people over 14 in the family) + (0.3 * number of people under 15 in the family))
  • FAMANDOVERFORSEL = FAMOEVRIG_OVERFORSEL_13 + FAMGRON_CHECK (from 2010) famdagpenge_kontant_13
FAMDAGPENGE_KONTANT_13 = FAMARBLHUMV + FAMOVRIG_DAGPENGE_AKAS_13 + FAMKONTANTHJ_13 + FAMOVRIG_KONTANTHJALP_13 + FAMSYG_BARSEL_13
  • FAMDISPONIBEL = FAMSUMINDKNETTORENT - FAMSKATMVIALT - FAMUNDERHBIDRAG famdisponibel_13
FAMDISPONIBEL_13 = FAMINDKOMSTIALT_13 + FAMLEJEV_EGEN_BOLIG - FAMRENTEUDGIFTER_13 - FAMSKATMVIALT_13 - FAMUNDERHBIDRAG
  • FAMERHVERVSINDK = FAMLOENMV + FAMVIRKOVERSKUD
  • FAMFORMUEINDK = FAMRENTEINDK + FAMOEVRIGFORMUE + FAMLEJEVAERDI famfradragialt
FAMFRADRAGIALT = FAMBRUTTOINDK - FAMSKATPLIGTIGINDK - FAMARBMABIDRAG (from 1994)

famindkomstialt_13

FAMINDKOMSTIALT_13 = FAMERHVERVSINDK_13 + FAMOFF_OVERFORSEL_13 + FAMPRIVAT_PENSION_13 + FAMRENTEINDK_13 + FAMOEVRIGFORMUE_13 + FAMRESTINDK_13

fammidlertidyd

FAMMIDLERTIDYD = FAMKONTANTHJAELP + FAMARBEJDSLOESP + FAMORLOVSYDELSE + FAMRESTBISTANDYD

fampensionialt

FAMPENSIONIALT = FAMPENSOFFENTLIG + FAMPENSIONATP + FAMEFTERLOEN + FAMOVERGANGYD (1994-2006) + FAMPENSTJENESTE (from 1991) + FAMANDENPENSION

famrestindk

FAMRESTINDK = FAMINDKOMSTIALT - FAMERHVERVSINDK - FAMOVERFOERINDK - FAMFORMUEINDK
  • FAMSKATMVIALT = FAMSKATTOT + FAMARBMABIDRAG famsumindknettorent
FAMSUMINDKNETTORENT = FAMINDKOMSTIALT + FAMLEJEVAERDI - FAMRENTEUDGIFTER

Worth knowing:

  • pnr: Not in DST’s variable list for FAIK, which documents the register as keyed on the household. Where it is present, the household’s row is repeated once per family member, so joining on familie_id alone multiplies rows.
  • familie_id: There is no person identifier here. Fetch familie_id from BEF for the relevant year, then join on it.
  • famaekvivadisp_13: This is the family’s disposable income divided by an equivalence factor, so that families of different sizes can be compared. The factor counts the first adult as 1.0, each further person over 14 as 0.5, and each child under 15 as 0.3: a couple with two young children comes to 1 + 0.5 + 0.6 = 2.1, so a family income of 420,000 is recorded as 200,000 for each of the four. FAMDISPONIBEL_13 is the same money before that division, and FAMAEKVIVAINDKNETTO is a different income concept (total income with net interest), so check which one your analysis plan means. The _13 suffix marks the definition that replaced the older variables from 2013: DST states that FAMDISPONIBEL was discontinued in 2013 and replaced by FAMDISPONIBEL_13. A study spanning 2013 has to know which side of that change it is on. DST’s year ranges settle the relationship with the sister column FAMAEKVIVADISP, which has no _13: the old one runs 1990-2012, this one runs 1987-2024. The _13 definition was applied backwards as well as forwards, so it is not a newer variable covering later years only. A study spanning the 2013 changeover should use _13 for the whole period rather than splicing the two, which would mix two definitions in one series.
  • year: Not a DST variable. It comes from fastreg’s parquet conversion, which concatenates the yearly deliveries, so it exists in the data you read but not in DST’s own documentation of this register.

SEPLINE classifies income as a 3-year mean against quintile cutpoints from the whole population with the same sex and 5-year age group, per year: Low, Medium or High. The recipe is in Socioeconomic variables.

AKM - Labour Classification Module

Labour market status per person per year.

Column Type Role Label Years
pnr character join key Personal identifier
socio13 integer code Socioeconomic classification, 2013 version 1991 to 2024
socio02 integer code Socioeconomic classification, 2002 version 2002 to 2013
socio integer code Socioeconomic classification, 1994-2001 version 1994 to 2001
socio_gl integer code Socioeconomic classification, 1976-1990 version 1976 to 1990
year integer date Register year
All other columns (41)
Column Type Role Label Years
beskst13 integer code Main source of income 1991 to 2024
disco08_alle_indk_13 character code Occupation code, DISCO-08 2010 to 2024
nace_db07_13 character code Industry, DB07 2007 to 2024
alder_ult_ink integer value Age at 31 December 1991 to 2024
ant_ansat_arbsted numeric value Number of employees at the main workplace 2006 to 2013
ant_ansat_arbsted_13 numeric value Number of employees at the main workplace, 2013 definition 2010 to 2024
ant_ansat_senr numeric value Number of employees in the main employment (by SE number) 1976 to 2005
atpsum2 numeric value Employment measure based on ATP contributions 1976 to 2010
beskst numeric code Employment status, 1980-2001 1976 to 2001
beskst02 numeric code Employment status, from 2002 2002 to 2013
branche_77 character code Danish industry code 1977, 1977-1993 1980 to 1999
brchi character code Industry code for owner 1976 to 2002
brchl character code Industry code for employee 1976 to 1999
cprtjek character code CPR check 1991 to 2024
cprtype character code CPR type 1991 to 2024
disco08_alle_indk character code Occupation code (DISCO-08), from 2010 2010 to 2013
disco08_loen_indk character code Occupation code (DISCO-08) for main employee job in the year 2010 to 2024
disco08_sel_indk character code Occupation code (DISCO-08) for self-employment 2010 to 2024
discoalle_indk character code Occupation code (DISCO), 1991-2009 1993 to 2009
discoloen_indk character code Occupation code (DISCO) for main employee job in the year 1991 to 2009
discosel_indk character code Occupation code (DISCO) for self-employment 1991 to 2009
discotyp character code Source of the employee’s DISCO code 1991 to 2024
disco_alle_indk_13 character code Occupation code (DISCO), 1991-2009, 2013 definition 1991 to 2009
funk_timeant numeric value Total hours worked in the year 2008 to 2024
nace character code Industry of main employment, 1992-2007 1992 to 2007
nacea character code Industry grouping of the workplace, 1993-2007 1992 to 2007
nacea_db07 character code Industry grouping of the workplace (DB07), from 2007 2007 to 2024
nacei character code Industry code of the business of the self-employed or assisting spouse, 1993-2007 1993 to 2007
nacei_db07 character code Industry grouping for owner (self-employed or assisting spouse, DB07), from 2007 2007 to 2024
nace_13 character code Industry of main employment, 1993-2007, 2013 definition 1993 to 2007
nace_db07 character code Industry of main employment (DB07), 2008-2013 2007 to 2013
nystgr character code Occupational grouping, 1980-1995 1980 to 1999
omfang character code Extent of tax liability 1991 to 2024
senr character code SE number (business identifier) 1985 to 2002
senri character code SE number of the business the person owns 1985 to 2002
senrl character code SE number of the employer 1985 to 1998
typ character code Job type 1980 to 1999
version character code Module data version 1991 to 2024
virkf numeric value Ownership type of the workplace with the highest earnings 2001 to 2013
virkfa numeric value Ownership type of the workplace with the highest wage income or hours 2001 to 2024
virkf_13 numeric value Ownership type of the workplace with the highest earnings, 2013 definition 2001 to 2024
  • beskst13: A different question from socio13: where the money came from, rather than what the person’s labour market position was. A source does now exist (https://www.dst.dk/da/TilSalg/data-til-forskning/generelt-om-data/ dokumentation-af-data/hoejkvalitetsvariable/ Personers-tilknytning-til-arbejdsmarkedet-set-over-hele-aaret–AKM-/BESKST13, checked 2026-09-09), a large classification with its own PDF supplement for edge cases, linked rather than transcribed. beskst13 differs from beskst02 in named ways (net rather than gross income for the self-employed, price-adjusted thresholds), which DST calls a difference rather than a break: see beskst02’s reader_note for the sharper break, between beskst02 and the older beskst.
  • disco08_alle_indk_13: Occupation, not socioeconomic position. DISCO-08 only starts in 2010; 1991-2009 uses the older disco_alle_indk_13 with a different code set, so an occupation series across 2010 is not continuous.
  • nace_db07_13: Industry classification from 2007. The pre-2007 series uses nace_13, which is a different classification rather than a renamed one.
  • alder_ult_ink: Age at the end of the year, not at your index date. Recompute from a birth date if the exact age matters.
  • beskst: Not comparable with beskst02, in DST’s own words, not just a difference of degree. Source: https://www.dst.dk/da/TilSalg/data-til-forskning/ generelt-om-data/dokumentation-af-data/hoejkvalitetsvariable/ Personers-tilknytning-til-arbejdsmarkedet-set-over-hele-aaret–AKM-/BESKST02 (checked 2026-09-09). People with an unemployment share over 50 percent, and people on efterløn (early retirement pay), get their own codes under beskst02 that beskst does not have, and the rules for who counts as self-employed also changed. A study spanning 2001-2002 should not treat this as a relabelled continuation of the same variable.
  • beskst02: Not comparable with beskst (see beskst’s own reader_note): DST states this directly, not just a difference of degree. Comparable with beskst13 with named exceptions (net vs gross self-employment income, price adjustment); see beskst13’s reader_note.
  • branche_77: DST flags a data break both within this variable and across variables. The five-digit 1977 industry classification was replaced by the six-digit NACE code in 1993; for 1994-1996 DST derives this code from NACE, so those years are a translation rather than an original coding. Use nace from 1992.
  • discoalle_indk: DST flags a data break both within this variable and across variables. For employees the code comes from the workplace with the highest pay in 1991-2008, but from the workplace with the most hours from 2009. The code has four digits in 1991-2002 and six from 2003, where the last two digits subdivide the four-digit code. Replaced by disco08_alle_indk in 2010.
  • discotyp: Where the occupation code came from, including whether it was imputed. DST flags a data break within this variable: job titles stopped being used for imputation in 2000, merged unemployment funds could no longer be used from 2003, and corrected company identification in 2014 moved many people to a different source. Worth checking before treating an occupation as observed.
  • disco_alle_indk_13: DST flags a data break within this variable. The workplace it is taken from changes in 2009 (highest pay before, most hours from then), and the code has 1-4 significant digits in 1991-2002 and six digits from 2003. DST advises care when comparing over time on more than the first one or two digits. From 2010 the series continues as disco08_alle_indk_13, on a different code set.
  • nace: DST flags a data break both within this variable and across variables. It uses Danish industry code 1993 for 1992-2002 and code 2003 for 2003-2007, and is replaced by nace_db07 from 2008. Blank, 0, 000000 and 999999 mean no employment in the year or no code found, and before 2003 the code is set only for people whose main income is from work, so DST says a comparison across 2003 can only be made for those people.
  • nace_13: DST flags a data break both within this variable and across variables. It uses Danish industry code 1993 for 1993-2002 and code 2003 for 2003-2007. Before 2003 it is set only for people whose main income is from work (socio13 below 140); from 2003 also for people with a job whose main income is a pension or a transfer. Continued by nace_db07_13.
  • nace_db07: DST flags a data break across variables: this replaces nace on a new classification (DB07), so codes do not carry across the 2007/2008 boundary. For 2007 DST imputed the values.
  • nystgr: DST flags a data break both within this variable and across variables, and says its quality falls after 1990, because the job title in CPR was only updated when a person moved and reported a change. For employees the code was set from different sources before 1993 and in 1993-1995.
  • omfang: DST flags a data break within this variable: before 2010 the set of values depends on who was in the tax authority’s final assessment register that year. Code 1 is the population DST publishes on (at least 15 at year end, fully taxable all year, resident in Denmark at the start and end of the year). Code 5 (dead and not assessed) exists only from 2002; before that those people have code 2.

No published source gives a data type for 46 of these 47 columns, so the Type column is our own assumption. Check with sapply(class) on a row of your own data before relying on it, especially for code columns, which lose their leading zeros if they arrive as numbers.

Join key: pnr.

Joins to other registers:

  • pnr joins to BEF (many-to-one).
Value sets for the coded columns (11)
Code system Values
socio13 11 Selvstændige, 110 Selvstændige, 111 Selvstændige erhvervsdrivende med 10 eller flere ansatte, 112 Selvstændige erhvervsdrivende med 5-9 ansatte, 113 Selvstændige erhvervsdrivende med 1-4 ansatte, 114 Selvstændige erhvervsdrivende uden ansatte, 12 Medarbejdende ægtefælle, 120 Medarbejdende ægtefælle, 13 Lønmodtagere, 131 Lønmodtagere med ledelsesarbejde, 132 Lønmodtager i arbejde der forudsætter færdigheder på højeste niveau, 133 Lønmodtager i arbejde der forudsætter færdigheder på mellemniveau, 134 Lønmodtager i arbejde der forudsætter færdigheder på grundniveau, 135 Andre lønmodtagere, 139 Lønmodtager uden nærmere angivelse, 21 Arbejdsløs mindst halvdelen af året, 210 Arbejdsløse mindst halvdelen af året, 22 Sygedagpenge, orlov mv., 220 Modtager af sygedagpenge, uddannelsesgodtgørelse, orlovsydelser mv., 31 Uddannelsessøgende, 310 Under uddannelse, inkl. skoleelever på min. 15 år, 32 Pensionist/efterløn, 321 Førtidspensionister, 322 Folkepensionister, 323 Efterlønsmodtagere mv., 33 Kontanthjælp, 330 Kontanthjælpsmodtagere, 41 Andre, 410 Andre, 42 Børn, 420 Børn under 15 år, ultimo året
beskst02 01 Selvstændig, 02 Medarbejdende ægtefælle, 03 Lønmodtager og ejer af virksomhed, 04 Lønmodtager, 05 Lønmodtager med understøttelse, 06 Pensionist og ejer af virksomhed, 07 Pensionist, 08 Øvrige, 09 Efterlønsmodtager, 10 Arbejdsløs mindst halvdelen af året (nettoledighed), 11 Modtager af dagpenge (aktivering og lign., sygdom, barsel og orlov), 12 Kontanthjælpsmodtager, 99 Ikke i AKM
disco08 Not listed here - see DST’s classification
nace_db07 Not listed here - see DST’s classification
beskst 01 Selvstændig, 02 Medarbejd., 03 Lønmodt. m. virksom., 04 Lønmodtager, 05 Lønmodtager med understøt., 06 Pensionist m. virksom., 07 Pensionist, 08 Øvrige, 99 Ikke i AKM
branche_77 Not listed here - see DST’s classification
disco_old Not listed here - see DST’s classification
discotyp 0 Uoplyst, 1 Stat, 2 Kommune, 3 A-kasse, 4 Privat virksomhed, mindst 10 ansatte, 5 CPR (1991-1999), 6 Foregående år, samme arbejdsgiver og arbejdssted (2004-), 7 Uddannelse igangværende, 8 A-kasse og branchekode, 9 Uddannelse afsluttet + branche, 10 Danmarks Statistiks e-indkomstregister
nace_old Not listed here - see DST’s classification
nystgr Not listed here - see DST’s classification
omfang 0 Børn under 15 år og uden indkomst og formue (1998-2001), 1 Fuldt skattepligtig og har bopæl både primo og ultimo året, 2 Har ikke boet i Danmark hele året, eller er død i løbet af året, 3 Findes i oplysningsseddelregisteret men ikke i slutligningsregisteret (fra 2002), 4 Personer under 15 år uden indkomst, samt personer der ikke er skattepligtige, 5 Er død (bobehandlingskode) og ingen indkomst i slutligningsregisteret, 6 Indkomst usandsynlig for mindst en person i familien, kan ikke rettes konsistent
  • socio13: Two codes are easy to misread. 410 is Andre (other), not unemployed: the unemployed are 210. And 420 is children under 15, a known category rather than a missing value, so it appearing in an adult cohort means the index date is wrong rather than the data being incomplete.
  • beskst02: Not comparable with beskst (see beskst’s own reader_note): DST states this directly, not just a difference of degree. Comparable with beskst13 with named exceptions: self-employment income is measured net of capital income in beskst13 rather than gross, and beskst13’s amount thresholds are price-adjusted where beskst02’s are not. A study spanning both should read DST’s own change note before treating them as one continuous series.
  • disco08: The AKM columns do not draw purely from this file. Checked against disco08_alle_indk’s own value list on DST’s high-quality variable page: only 564 of its 790 distinct codes appear in this CSV’s 564 level-5 codes. disco_typ (see discotyp.yaml) explains why: the occupation code for a given person-year can come from several source registers of varying vintage and quality, including imputation, so a study will see codes this file’s current edition does not carry. Do not treat a code missing from this CSV as an error in the data before checking discotyp.
  • nace_db07: Two things to check before using this as a lookup. First, format: this file writes the detailed code with dots (01.11.00); nace_db07 and nace_db07_13 hold it without them (011100). Second, coverage: checked against nace_db07’s own value list on DST’s high-quality variable page, only 490 of its 743 distinct codes match this file’s 738 level-2 codes even after stripping dots. As with DISCO-08 (see disco08.yaml), the industry code for a given person-year can be sourced from more than one register, so a code absent from this CSV is not necessarily an error.
  • beskst: Not comparable with beskst02, in DST’s own words, not just a difference of degree: people with an unemployment share over 50 percent, and people on efterløn (early retirement pay), get their own codes under beskst02 that this code list does not have, and the rules for who counts as self-employed also changed. See beskst02’s reader_note.
  • branche_77: Superseded by NACE (see nace), which the AKM register also carries for overlapping years. A study reaching back before 1992 needs this code list; one starting later should prefer NACE or DB07 rather than reading a code DST had already retired.
  • disco_old: Do not read a code here against DISCO-08’s published list (disco08.yaml): the two classifications share the general numeric shape but DST revised the detail at the 2010 switch, and a code that means one occupation in DISCO-08 is not guaranteed to mean the same thing, or to exist at all, in the pre-2010 scheme.
  • discotyp: A different question from the DISCO occupation code itself: this says where that code came from, not what the job was. DST’s own page states that DISCO code quality is best when discotyp is 1, 2, 4 or 10, and that the remaining codes mean the DISCO code was set by imputation.
  • nace_old: Do not read a code here against DB07/NACE Rev.2’s published list (nace_db07.yaml): the 2007-2008 revision changed the code structure, and a code that means one industry under DB07 is not guaranteed to mean the same thing, or to exist at all, under this older scheme.
  • nystgr: Retired in 1995 and replaced by DISCO. A code’s meaning can shift within the window a study covers: DST’s own page notes that code 5100 changed meaning in 1992 (the group it now names used code 5500 before that year), so a series spanning 1992 needs the year-by-year note on the source page, not just the current label.
  • omfang: Code 2 changed meaning at the 2002 boundary: before 2002 (and again 2002-2009) it also absorbed children under 15 with no income or wealth, a group that codes 0 and 4 cover separately in other years. Code 5 (died, not settled) only exists from 2002; before that, a death with no settled income was coded 2 instead. DST does not publish exact boundary dates for this drift the way it does for codes 0 and 3 (see above), so treat “2002” as DST’s own rounding, not a verified cutover date. DST’s own publications and statistikbanktabeller are restricted to omfang=1: an analysis that does not filter on it silently includes partial-year residents, the newly dead, and unsettled records alongside ordinary full-year taxpayers.

Where these values come from:

Worth knowing:

  • socio13: This is the version to use. It runs from 1991, so it reaches back further than its name suggests and covers the periods of the three older versions as well.
  • socio02: Uses socio13’s lookup, but the two do not fully agree. Checked 2026-09-09 against DST’s own value tables (https://www.dst.dk/da/TilSalg/ data-til-forskning/generelt-om-data/dokumentation-af-data/hoejkvalitetsvariable/ Personers-tilknytning-til-arbejdsmarkedet-set-over-hele-aaret–AKM-/SOCIO02): code 111 here is “10 or more employees”, the same boundary socio13 uses, so socio02 and socio13 read together safely. socio (the 1994-2001 predecessor) is the one that disagrees: see its own reader_note.
  • socio: Uses socio13’s lookup, but the two do not agree on code 111. Checked 2026-09-09 against DST’s own value tables (https://www.dst.dk/da/TilSalg/ data-til-forskning/generelt-om-data/dokumentation-af-data/hoejkvalitetsvariable/ Personers-tilknytning-til-arbejdsmarkedet-set-over-hele-aaret–AKM-/SOCIO): here, 111 is “selvstaendig med 50 eller flere ansatte” (self-employed, 50+ employees). In socio02 and socio13, the same code 111 is “10 eller flere ansatte” (10+ employees). The size boundary moved and the code did not change, so a self-employed person with, say, 20 employees is 111 in one era and a different code in the other, with nothing in the data to flag the switch.
  • year: Not a DST variable. It comes from fastreg’s parquet conversion, which concatenates the yearly deliveries, so it exists in the data you read but not in DST’s own documentation of this register.

SEPLINE’s main groups for socio13 (Table 6, with the corrigendum):

  • A: Working: 110-114, 120, 131-135, 139, and students (310)
  • B: Unemployed: 210, 410
  • C: Outside workforce: 220, 321, 330
  • D: Retired: 322, 323
  • Missing/other: 0, 420 (children under 15), or no record

The recipe, with the subgroups, is in Socioeconomic variables.

9. Project-specific registers

Many projects have access to registers beyond the standard list above - e.g. quality registers from clinical databases or pre-computed classification files.

These are project-specific and not available in all projects on DST.

Examples are private hospitals (priv_adm, priv_diag, priv_skspor - structured in parallel with LPR) and various clinical quality registers. Availability varies from project to project.

Working on DARTER / project 708421?

The project uses among others DBSO (the Danish Obesity Treatment Database) and OSDC (Open Source Diabetes Classifier).

Data resource profiles and reporting

Data resource profiles are the papers you cite when you describe a register in your methods section: they document the register’s content, coverage and validity. Cite the profile for each register you use.

Register Data resource profile
The Danish health-care system and epidemiological research (overview) Schmidt et al. 2019, Clin Epidemiol - doi:10.2147/CLEP.S179083
CPR (Civil Registration System) Schmidt, Pedersen & Sørensen 2014, Eur J Epidemiol - doi:10.1007/s10654-014-9930-3
LPR (National Patient Registry) Schmidt et al. 2015, Clin Epidemiol - doi:10.2147/CLEP.S91125
LMDB (Prescription Registry) Pottegård et al. 2017, Int J Epidemiol - doi:10.1093/ije/dyw213
Cause of Death Register Helweg-Larsen 2011, Scand J Public Health - doi:10.1177/1403494811399958

Reporting: report observational studies following STROBE. For register-based / routinely-collected-data studies, RECORD extends STROBE, and RECORD-PE covers pharmacoepidemiology specifically - see RECORD-PE (EQUATOR Network).

Back to top