Consider: when does your follow-up extend to, and are the registers updated up to that date? An outdated extraction cuts off censoring dates and outcomes too early - no error message, just silently wrong results. If the registers do not cover your study period, you need to order a new extraction from DST.
Important
The column names are checked on DARTER (project 708421) in June 2026 - not necessarily on your project. Names are shown afterrename_with(tolower) has been called. In your own project folder, both which columns exist and their spelling - including upper/lower case - may look different. Always verify against your own files with colnames() (see Phase 7 - Inspect your data).
Key columns - the ones you actually use in the code - are marked in bold.
Note
Opening registers - two ways: The code examples on this page use open_dataset("path/to/register/") as a generic placeholder - replace with the path to your project’s parquet folder. With fastreg, use read_register("registername") instead (by name). DARTER users can use read_register("registername") - see DARTER - Register paths and datastores.
See Pitfalls for special quirks with each register. Column names apply after rename_with(tolower) - inspect your own register with colnames() if something does not match.
Tip
Looking for “which register contains X?” - start with the decision table in Phase 8 - Find your registers. This page is the deep reference with full column names, types and code examples.
Status register - one snapshot per person per reference time point (ultimo the period). Delivered quarterly since 2008 (March, June, September, December); before 2008 December only. Whether aar == 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 DODSAARS to determine whether a person was alive on a specific date.
Column
Type
Contents
pnr
character
Personal identifier
koen
numeric
Sex: 1 = male, 2 = female
foed_dag
Date
Date of birth
aar
integer
Register year (one record per year)
familie_id
character
Household key - join to FAIK
reg
character
Region
civst
character
Marital status
Note
BEF does not contain date of death. Use DODSAARS (d_dodsdto) for censoring. See DST’s official BEF documentation: statistikdokumentation/befolkningen →
DODSAARS - Death Register
One row per deceased person.
Note
Coverage period and availability depends on your project’s cleaned-data. Check the modification date and ask your data manager about current coverage.
Column
Type
Contents
pnr
character
Personal identifier
d_dodsdto
Date
Date of death - use this for censoring
fdato
Date
Date of birth
c_sex
character
Sex
v_alder
numeric
Age at death
year
integer
Year of death
c_dod1
character
Underlying cause of death (ICD-10)
c_dod2–c_dod4
character
Contributing causes of death
c_dodskom
character
Manner/place of death
c_bopkom
character
Municipality of residence at death
Warning
dodsaasg is the classification register for causes of death - it is not the source for individual death dates. Always use dodsaars with the column d_dodsdto.
VNDS - Migration Register
One row per migration event per person.
Column
Type
Contents
pnr
character
Personal identifier
indud_kode
character
"U" = emigration (use for censoring), "I" = immigration
haend_dato
Date
Event date
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.
Psychiatric contacts before March 2019 are in separate registers from somatic LPR2. From March 2019, LPR3 covers both in one table.
Note
Before 1995: inpatients only, and ICD-8. The Danish Psychiatric Central Register is electronic from 1969, but covers only inpatients until 1995, and diagnoses before 1994 are coded in ICD-8 (numeric codes, e.g. 290-315) - not ICD-10 F-codes. These older data are normally not part of the standard extract and are requested separately via Rigsarkivet. See also Understand LPR.
Warning
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
Column names differ from somatic LPR2 - rename at load:
LPR3 covers both somatic and psychiatric contacts in one table. Join: lpr_a_kontaktLEFT JOINlpr_a_diagnoseONdw_ek_kontakt.
Note
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 - you still need to filter on diag_kode_type.
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.
Note
No pnr in the procedure tables.pnr is fetched via join to lpr_adm (LPR2) or lpr_a_kontakt (LPR3) respectively.
Intended join key to lpr_a_kontakt - but many NA on DARTER, see note below
dw_ek_kontakt
character
NA for all rows in this parquet file on DARTER (see note below)
procedurekode
character
SKS procedure code - use this for matching (e.g. "KJDF10")
dato_start
Date
Procedure date
proceduretype
character
"P" = procedure, "+" = add-on code
procedurekode_parent
character
Parent procedure code
proceduretype_parent
character
Parent procedure type
tidspunkt_start
datetime
Procedure start time
dato_slut
Date
Procedure end date
tidspunkt_slut
datetime
Procedure end time
lprindberetningssystem
character
LPR reporting system
sorenhed_pro
character
SOR unit for the procedure
procedureregistrering_id
character
Internal registration ID
Warning
The join from procedurer_kirurgi to lpr_a_kontakt is not yet resolved on DARTER (under investigation).dw_ek_kontakt is NA for all rows in DARTER’s parquet version (confirmed 2026-06-02), so the obvious join key can’t be used. dw_ek_forloeb looks like the alternative but also has many NA, so the pnr lookup isn’t solved yet. Applies to DARTER/project 708421 - check on your own project. We’ll update the page with a solution once one is found. Column names are mixed case in raw data - call rename_with(tolower) immediately after loading.
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. Column names are not verified here - see DST’s variable list for LPR_SKSUBE and confirm with colnames().
Combination across the full period
See the code example: combination across the full period
# Replace [projectnumber] with your own project number# DARTER: use read_register("registername") instead of open_dataset("path")# SKS from LPR2 (up to 2018)surg_lpr2 <-open_dataset("path/to/lpr_sksopr/") %>%rename_with(tolower) %>%filter(toupper(c_opr) %in%!!SKS_CODES) %>%# !! sends the local R vector to DuckDBleft_join(open_dataset("path/to/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_forloeb# NOTE: the join is unresolved on DARTER (many NA) - see the warning abovesurg_lpr3 <-open_dataset("path/to/procedurer_kirurgi/") %>%rename_with(tolower) %>%filter(toupper(procedurekode) %in%!!SKS_CODES) %>%# !! sends the local R vector to DuckDBleft_join(open_dataset("path/to/lpr_a_kontakt/") %>%rename_with(tolower) %>%select(dw_ek_forloeb, pnr),by ="dw_ek_forloeb" ) %>%select(pnr, surgery_date = dato_start, surgery_code = procedurekode) %>%collect()# Combinedsurg_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().
The Cancer Register
The gold standard for incident cancer diagnoses - more complete and precise for cancer than LPR diagnoses. One row per tumour; join to your population via pnr. Covers many decades back (modern coding with ICD-10 + ICD-O morphology/topography). Use it for cancer as outcome or exclusion. Variable names: see DST’s variable list.
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 (specialty, service code, date) are named differently in sysi and sssy - verify with colnames().
Laboratory results - laboratorieproevesvar_
Laboratory/blood test results (e.g. HbA1c, lipids). A very large register - over 2.2 billion rows, so filter with arrow/duckplyr before you collect() into R. Central fields: pnr, NPU code (analyte type) and sample date. samplevalue is character (not numeric), because some results are coded in natural language (e.g. "ikke påvist", "negativ") - handle that before computing on the values. Name and availability are project-/DARTER-specific.
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
One row per dispensed prescription. Covers approximately 1994 onwards.
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.
Household-equivalised disposable income per year. Link: join BEF (pnr, familie_id, aar) with FAIK (familie_id, aar).
Column
Type
Contents
familie_id
character
Household key - join to BEF
famaekvivadisp_13
numeric
Household-equivalised disposable income
aar
integer
Register year
Income quintiles are calculated as 3-year averages compared against Q20/Q40/Q60/Q80 cut-points from the full BEF population stratified by sex × 5-year age group × reference year.
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.
Tip
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 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)
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).