Byg din studiepopulation

Identificér dine cases/eksponerede - vælg derefter studiedesign

Published

July 2, 2026

De senere faser - udtræk af variable (Fase 11), saml datasættet (Fase 12) og analyse (Fase 13) - forudsætter, at du allerede har en kohorte: en tabel med pnr og index_date per person. Denne side viser, hvordan du identificerer din studiepopulation og giver hver person en index-dato; derefter vælger du studiedesign.

Tip

Kort fortalt: Først identificerer du dine cases/eksponerede og giver hver en index-dato. Derefter afhænger vejen af dit design:

Hvad er index-dato?

Index-dato er det tidspunkt der markerer starten på opfølgning for en given person.

  • Eksponerede: den dato personen fik eksponeringen (fx operationsdato, diagnosedato, første receptudstedelse)
  • Sammenligningskohorte: den index-dato der er tildelt fra den matchede eksponerede

Alt efterfølgende - udfaldsdato, kovariater ved baseline, opfølgningstid - beregnes relativt til index-dato. Definitionen af index-dato er afgørende for studievaliditeten.

Warning

Denne side er stadig under udvikling. Koden skal gennemgås og testes yderligere inden den bruges direkte. Brug den som strukturel vejledning og tilpas til dit eget projekt.

Note

Funktioner brugt her. inner_join() og bind_rows() er allerede vist i Udtræk fra LPR og gennemgås grundigt i Kobl udtræk sammen. group_by() + slice() forklares i Langt ↔︎ bredt format. Nyt i Trin 2: anti_join(), distinct(), pull() samt nrow(), cat() og stopifnot() - se Guide til funktioner.


Trin 1 - Identificér de eksponerede (eller cases)

Du scanner det register der definerer din eksponering. Du har endnu ingen kohort_pnrs-liste - du forespørger hele registret og filtrerer på eksponeringskriteriet.

Eksponeringen kan defineres på mange måder:

Type Eksempel Register
Operation / procedure (SKS-kode) Bariatrisk kirurgi KJDF10/KJDF11 lpr_sksopra (LPR2), procedurer_kirurgia (LPR3)
Hospitaldiagnose (ICD-kode) Type 2-diabetes E11 lpr_diag + lpr_adm, lpr_a_diagnose + lpr_a_kontakt
Medicineksponering (ATC-kode) Metformin A10BA02 LMDB
Klinisk mål / biomarkør BMI > 35, HbA1c > 75 mmol/mol Projektspecifikke data / OSDC / DBSO

a lpr_sksopr og procedurer_kirurgi er navnene på DARTER-projektet (708421) - se Register-overblik. Navnene kan variere på andre projekter.

Eksempel A: SKS-koder (operation/procedure)

lpr_sksopr indeholder operationskoden (c_opr) + recnum, men ikke pnr eller dato; dem ligger i lpr_adm. Derfor joiner du de to på recnum for at få person + dato + operation samlet - præcis samme mønster som diagnoser (kontakt- + diagnoseregister), se Forstå LPR.

#=====================================================
# Trin 1A: identificér eksponerede via SKS-koder
#=====================================================
library(arrow)    # open_dataset
library(dplyr)    # filter, select, group_by, slice, ungroup, bind_rows, mutate

# Tilpas disse koder til dit studie
RYGB     <- c("KJDF10", "KJDF11")                     # Roux-en-Y gastric bypass
SG       <- c("KJDF40", "KJDF41", "KJDF96", "KJDF97") # sleeve gastrectomy
BS_KODER <- c(RYGB, SG)                               # samlet vektor

#-----------------------------------------------------
# LPR2: indgreb frem til 2018/2019
#-----------------------------------------------------
lpr_sksopr <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/lpr_sksopr/") %>%
  rename_with(tolower)
lpr_adm    <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/lpr_adm/") %>%
  rename_with(tolower)

eksp_lpr2 <- lpr_sksopr %>%
  filter(c_opr %in% !!BS_KODER) %>%                        # kun bariatri-indgreb
  select(recnum, sks_kode = c_opr) %>%                      # recnum er join-nøgle til lpr_adm
  inner_join(
    lpr_adm %>% select(pnr, recnum, index_date = d_inddto), # tilknyt pnr og dato
    by = "recnum"
  ) %>%
  collect()

#-----------------------------------------------------
# LPR3: indgreb fra 2019 og frem
#-----------------------------------------------------
proc_kir <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/procedurer_kirurgi/") %>%
  rename_with(tolower)
lpr_a_k  <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/lpr_a_kontakt/") %>%
  rename_with(tolower)

eksp_lpr3 <- proc_kir %>%
  filter(procedurekode %in% !!BS_KODER) %>%                 # kun bariatri-indgreb
  select(dw_ek_forloeb, sks_kode = procedurekode) %>%
  inner_join(
    lpr_a_k %>% select(pnr, dw_ek_forloeb, index_date = kont_starttidspunkt),
    by = "dw_ek_forloeb"
  ) %>%
  collect() %>%
  mutate(index_date = as.Date(index_date))                  # datetime → dato

#-----------------------------------------------------
# Kombinér og tag ét indgreb per person (det første)
#-----------------------------------------------------
# Resultatet hedder "eksponerede" - kun den eksponerede gruppe, IKKE den fulde kohorte endnu
eksponerede <- bind_rows(eksp_lpr2, eksp_lpr3) %>%
  group_by(pnr) %>%                                        # gruppér per person
  arrange(index_date) %>%                                   # ældste dato øverst
  slice(1) %>%                                              # ét indgreb per person (det første)
  ungroup() %>%                                             # frigiv gruppering (se Fase 12)
  mutate(exposed = 1L)                                      # markér som eksponeret (1 = ja)

nrow(eksponerede)                                           # antal unikke opererede
Tip

eksponerede indeholder kun de opererede. Den fulde kohorte (eksponerede + sammenligningskohorte) bygges på Sammenligningskohorte og gemmes som kohort. Det er kohort - ikke eksponerede - du bruger som kohort_pnrs i de øvrige faser.

Eksempel B: ICD-diagnose som eksponeringskriterium
#=====================================================
# Trin 1B: identificér eksponerede via ICD-diagnose
#=====================================================
# Samme LPR-mønster som Fase 9 - men uden semi_join(tibble(pnr = kohort_pnrs), by = "pnr"),
# da kohorte endnu ikke er bygget. Du søger hele befolkningens data for at finde eksponerede.
lpr_diag <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/lpr_diag/") %>%
  rename_with(tolower)
lpr_adm  <- open_dataset("E:/workdata/[projektnummer]/cleaned-data/parquet-registers/lpr_adm/") %>%
  rename_with(tolower)

eksponerede <- lpr_adm %>%
  inner_join(
    lpr_diag %>%
      filter(c_diagtype %in% c("A", "B"),
             substr(c_diag, 2, 4) == "E11") %>%             # T2D: "DE11" → strip D-præfiks
      select(recnum, c_diag),
    by = "recnum"
  ) %>%
  select(pnr, index_date = d_inddto) %>%
  collect() %>%
  group_by(pnr) %>%
  arrange(index_date) %>%
  slice(1) %>%                                              # første diagnose per person
  ungroup() %>%
  mutate(exposed = 1L)
Note

Dette eksempel henter kun fra LPR2. Tag altid stilling til, hvilke registre dit udfald/din eksponering kræver - LPR2 (evt. + psykiatri) og LPR3 - og kombinér dem som i 9b: Udtræk fra LPR. Udelader du et register, mister du de tilfælde, der kun findes der.


Trin 2 - Ekskludér prævalente tilfælde

Personer der allerede havde dit outcome før index-dato skal ekskluderes - ellers tæller de som nye tilfælde, selvom de ikke er det. Det gælder alle designs, også et prævalensstudie uden sammenligningsgruppe, så det hører til her, hvor du bygger den eksponerede kohorte.

Tæl hvor mange der ryger fra ved hvert eksklusionstrin, så du kan beskrive frafaldet og senere tegne et STROBE flow-diagram (også kaldet et deltager- eller attrition-diagram; se STROBE-checklisten). Den generiske N-optællings-skabelon står i Fase 6.

Hjælpefunktion til at ekskludere prævalente tilfælde

Skal samme tjek bruges flere gange (fx også på en sammenligningsgruppe senere, se Sammenligningskohorte), kan du pakke logikken i en funktion, så de to tjek ikke skrider fra hinanden. Se God kode-praksis.

Vis koden: ekskludér prævalente tilfælde
#=====================================================
# Trin 2: ekskludér prævalente tilfælde
#=====================================================
# diagnoser = dit LPR-udtræk fra Fase 9 (kolonner: pnr, date_contact, icd3)
OUTCOME_KODER <- c("G30", "F00", "F01", "F02", "F03")   # ICD-10 for dit outcome - tilpas

# Vi laver vores EGEN funktion (en genbrugelig kodeblok). Den tager tre argumenter:
#   diagnoser = dit LPR-diagnoseudtræk (kolonner: pnr, date_contact, icd3)
#   koder     = ICD-koderne der definerer dit outcome (her OUTCOME_KODER)
#   kohorte   = den gruppe der skal tjekkes, med pnr + index_date
# Den returnerer de pnr, der havde outcome FØR deres egen index-dato.
prior_outcome_pnrs <- function(diagnoser, koder, kohorte) {
  diagnoser %>%
    filter(icd3 %in% koder) %>%
    inner_join(kohorte %>% select(pnr, index_date), by = "pnr") %>%  # tilknyt hver persons index
    filter(date_contact < index_date) %>%                            # kun kontakter FØR index
    distinct(pnr) %>%                                                 # én række per person
    pull(pnr)                                                         # vektor af pnr at ekskludere
}

praevalente <- prior_outcome_pnrs(diagnoser, OUTCOME_KODER, eksponerede)

n_before <- nrow(eksponerede)                 # nrow() = antal rækker (her: antal personer)
eksponerede <- eksponerede %>%
  filter(!pnr %in% praevalente)               # behold kun dem UDEN prævalent outcome

# cat() printer bare en læsbar linje i konsollen, så du kan følge frafaldet undervejs.
cat("Efter prævalens-eksklusion:", nrow(eksponerede),
    "| ekskluderet:", n_before - nrow(eksponerede), "\n")
# Er beskeden kun til dig selv, kan du nøjes med:  nrow(eksponerede)   # antal tilbage

stopifnot(n_distinct(eksponerede$pnr) == nrow(eksponerede))   # tjek: én række per person
Tip

nrow(), cat() og stopifnot() er forklaret i Guide til funktioner.

Tip

Planlægger du en sammenligningskohorte? Så udtræk gerne outcome- (og eksponerings-)datoerne for hele befolkningen allerede her - ikke kun for de eksponerede - og genbrug dem: i Trin 2 afgrænset til de eksponerede (som ovenfor), og senere til sammenligningspoolen (se Sammenligningskohorte). Outcome-udtrækket på diagnosekoderne returnerer alligevel alle med diagnosen, så du sparer en ekstra forespørgsel mod registrene.


Deltagerdiagram (STROBE flow)

De N-optællinger, du lavede i Trin 1 og Trin 2, samles til sidst i et STROBE flow-diagram: en figur, der viser hvor mange personer der var med fra start, hvor mange der blev ekskluderet ved hvert trin og hvorfor, og hvor mange der endte i studiepopulationen. Det forventes i næsten alle observationelle studier. Diagrammet her viser også hvor dataene kommer fra i hvert trin (tallene er simulerede).

flowchart TD
    A[("Kilderegistre - hele befolkningen<br>LPR2: lpr_sksopr + lpr_adm<br>LPR3: procedurer_kirurgi + lpr_a_kontakt")]:::store
    B["Trin 1: filtrér på eksponeringskoder<br>eksponerede med pnr + index_date<br>n = 12.300"]:::step
    E1["Ekskluderet i Trin 2:<br>prævalent outcome før index<br>(fra LPR-diagnoser)<br>n = 1.150"]:::excl
    C["Eksponeret kohorte<br>n = 11.150"]:::step
    F["Valgfrit (Fase 10a):<br>+ matchet sammenligningskohorte"]:::optional
    D["Endelig studiepopulation<br>pnr + index_date<br>(→ Fase 11)"]:::result

    A --> B
    B --> C
    B -.->|frafald| E1
    C -.-> F
    C --> D
    F -.-> D

    classDef store fill:#eef0f2,stroke:#8a94a6,color:#1f2733;
    classDef step fill:#eaf2fb,stroke:#4a78b5,color:#173a5e;
    classDef excl fill:#fdecea,stroke:#d9534f,color:#7a1f1a;
    classDef optional fill:#fff3e0,stroke:#e69500,color:#7a4f00;
    classDef result fill:#e9f7ef,stroke:#3fae6b,color:#14532d;

Sådan hænger hvert trin sammen med dataene:

  • Kilderegistre: hele befolkningens LPR-data (du har endnu ingen kohorteliste). LPR2 og LPR3 åbnes dovent med open_dataset() - se Trin 1 ovenfor.
  • Trin 1: du filtrerer på dine eksponeringskoder og knytter pnr + index_date på. Resultatet er eksponerede.
  • Trin 2 (eksklusion): prævalente tilfælde - personer med outcome før deres index-dato - findes i LPR-diagnoserne og fjernes. Det er n_before - nrow(eksponerede), der står i eksklusionsboksen.
  • Endelig studiepopulation: pnr + index_date per person, klar til Fase 11 - Udtræk variable. Bygger du en sammenligningskohorte, indsættes Fase 10a før det sidste trin.
Warning

Outputkontrol: eksklusionsboksene viser rå antal. Små tal (fx en eksklusionsgruppe med ganske få personer) kan være afslørende - rund af eller slå sammen, før diagrammet forlader DST. Se Fase 14 - Eksport og hjemsendelse.


Tip

Hvad nu - vælg dit design:

  • Prævalensstudie / kohorte uden sammenligningsgruppe: efter denne side er du færdig: du har din studiepopulation med en index-dato. Gå videre til Fase 11 - Udtræk variable og Fase 12 - Saml & klargør datasættet.
  • Kohortestudie med sammenligningskohorte: efter denne side fortsætter du til → Sammenligningskohorte, hvor du bygger en matchpool og risk-set matcher en sammenligningsgruppe.
  • (Nested) case-control: efter denne side fortsætter du til → Case-control, hvor din “eksponerede” gruppe ovenfor i stedet er dine cases, og du sampler kontroller der var i risiko, da casen fik udfaldet.

Se også

Back to top