Filtyper og hvordan de åbnes
Hvad du møder i din arbejdsmappe - og hvad der åbner det
Når du åbner Stifinder på DST-serveren, møder du filer med forskellige endelser. Denne side er dit opslagsværktøj: hvilken filtype er det, hvilken funktion åbner den, og kommer dataene ind i hukommelsen med det samme eller ej?
Det sidste - doven vs. fuld indlæsning - er den vigtigste skelnen på denne side. Mekanismen bag forklares i Fase 5 - Udtræk trin for trin; her skal du bare vide, hvilke filtyper der opfører sig hvordan.
Sådan ser en projektmappe ud
Et typisk projekt på DST-serveren er organiseret nogenlunde sådan her. Registrene ligger under cleaned-data/; dine egne scripts og resultater ligger under workspace/[eget-navn]/:
E:/rawdata/[projektnummer]/
├── Grunddata/ # rå registerdata fra DST (ofte SAS) - skrivebeskyttet
│ └── bef/ lpr_adm/ lpr_diag/ …
└── Eksterne data/
│ └── projektspecifikke udtræk mm/ …
E:/workdata/[projektnummer]/
├── cleaned-data/
│ └── parquet-registers/ # registre konverteret til parquet
│ └── bef/ lpr_adm/ lpr_a_kontakt/ …
└── workspaces/
└── [eget-navn]/ # dit eget arbejdsområde
├── R/ # dine analysescripts (01_, 02_, …)
├── datasets/ # dine egne mellemresultater (.rds)
└── output/ # tabeller, figurer og logs
Stierne i kodeeksemplerne følger denne struktur, men dine egne mappenavne kan sagtens være anderledes - tjek med Stifinder. To ting er værd at vide:
rawdata/er skrivebeskyttet. Du kan ikke redigere eller skrive i de rå registerdata, DST leverer. Du arbejder iworkspace/, hvor hver projektdeltager typisk har sin egen undermappe ([eget-navn]/) til scripts, mellemresultater og output.- Næsten al koden i denne guide forudsætter, at registrene er i parquet. Hvis dit projekt kun har rå SAS-filer, er første opgave at konvertere dem til parquet - og at sætte en fornuftig mappestruktur op til projektet. Se Konvertér SAS-filer til Parquet nedenfor.
Hvordan du selv navngiver scripts i R/, gennemgås i God kode-praksis.
Doven vs. fuld indlæsning - hvad er forskellen i praksis?
Det er den vigtigste skelnen på siden, så vi tager den først. Hver filtype nedenfor falder i én af to indlæsningsmåder.
Tænk på forskellen som to måder at handle på. Fuld indlæsning er at køre hele supermarkedet hjem og først derhjemme finde de tre varer, du skulle bruge. Doven indlæsning er at sende en indkøbsseddel og kun få de tre varer leveret. Når et register fylder millioner af rækker, er den forskel afgørende.
Fuld indlæsning (readRDS, read_sas, read_csv, read_xlsx) Hele filen læses ind i RAM (computerens arbejdshukommelse - den er begrænset og deles med alle andre på serveren) med det samme. For dine egne mellemresultater er det fint - de er relativt små. Men det ville crashe din session, hvis du prøvede det på et helt register.
Doven indlæsning (parquet via open_dataset()) Filen åbnes som en forbindelse til dataene på disken, ikke som selve dataene. Du kan filtrere og vælge kolonner (skrive din “indkøbsseddel”), og først når du kalder collect() hentes de udvalgte rækker ind i RAM. Det er sådan du arbejder med registre på millioner af rækker uden at løbe tør for hukommelse.
SAS-filer er også store - og deles med alle på serveren. På DST deler alle brugere serverens RAM. read_sas() på en stor SAS-fil belaster serveren for alle på samme tid. DST lukker automatisk processer (RStudio-sessioner, jobs m.m.) når RAM’en er ved at være fyldt - så et for stort udtræk kan koste dig dit ulagrede arbejde. Hvis du bruger en SAS-fil gentagne gange, er det værd at konvertere den til parquet én gang - det sparer markant RAM og gør indlæsning meget hurtigere. Se Konvertér SAS til parquet nedenfor for fremgangsmåden, og Pas på RAM i det fælles miljø for de praktiske vaner. DST’s officielle råd er samlet i DST-vejledning: Reduktion af RAM-forbrug i det fælles miljø (PDF).
Oversigt - filtype, pakke, funktion
| Filtype | Pakke | Funktion | Indlæsning |
|---|---|---|---|
.parquet / parquet-mappe |
arrow eller fastreg |
open_dataset("sti/til/mappe/") eller read_register("navn") |
Doven - intet i RAM før collect() |
.rds |
base R | readRDS("sti/til/fil.rds") |
Fuld - hele filen ind i RAM |
.sas7bdat |
haven |
read_sas("sti/til/fil.sas7bdat") |
Fuld - hele filen ind i RAM |
.csv |
readr |
read_csv("sti/til/fil.csv") |
Fuld - hele filen ind i RAM |
.xlsx |
readxl |
read_xlsx("sti/til/fil.xlsx") |
Fuld - hele filen ind i RAM |
Den sidste kolonne er doven/fuld-skelnen fra ovenfor: parquet er det eneste dovne format, alt andet læses fuldt ind i RAM.
Hvad skriver du i parenteserne?
- Med
open_dataset()(arrow) skriver du stien til parquet-mappen - fxopen_dataset("sti/til/bef/"). Den virker på alle parquet-filer, på alle projekter. - Med
read_register()(fastreg) skriver du bare registrets navn - fxread_register("bef")- fordi fastreg allerede ved, hvor dine parquet-data ligger (sat én gang under konverteringen). Den giver dig desuden en DuckDB-forbindelse, så flere dplyr-funktioner virker uden et ekstrato_duckdb()-trin. Den kræver, at registrene er sat op med fastreg.
Hvilken sti det konkret er, afhænger af dit projekt og din server. Kolonnenavne for hvert register finder du i Register-overblik.
Har du ikke selv konverteret dataene? Hvis en kollega allerede har konverteret registrene med fastreg, peger du bare fastreg på den mappe én gang per script - sæt options(fastreg.project_workdata_dir = "...") til den konverterede mappe (spørg den der satte det op om den præcise sti, typisk cleaned-data/parquet-registers/). Derefter virker read_register("bef") via navn, uden konvertering og uden en sti i hvert kald. Getting started-vignetten viser optionen.
Et register kommer ofte som mange årlige filer (fx bef2015.parquet, bef2016.parquet … i samme mappe, nogle gange én undermappe per år). Både open_dataset("sti/til/bef/") og fastregs read_register("bef") læser hele mappen (inkl. eventuelle års-undermapper) som ét samlet datasæt. Vælg år ved at filtrere på årskolonnen i dataene, fx filter(year == 2015) (nogle registre bruger aar).
RDS er det format du selv skriver mest. Du gemmer mellemresultater fra ét script og genindlæser dem i det næste:
saveRDS(kohort, "sti/til/full_cohort.rds") # gem et R-objekt til disk
kohort <- readRDS("sti/til/full_cohort.rds") # læs det ind igen i næste scriptSjældnere formater (Stata, SPSS, Feather, RData)
Disse møder du sjældent i et typisk DST-kohortestudie, men her er de for fuldstændighedens skyld:
| Filtype | Pakke | Funktion |
|---|---|---|
.dta (Stata) |
haven |
read_dta() |
.sav (SPSS) |
haven |
read_sav() |
.feather |
arrow |
read_feather() |
.rdata / .rda |
base R | load() |
.rdata/.rda adskiller sig fra .rds ved at kunne gemme flere objekter på én gang - men .rds er at foretrække, fordi du selv styrer hvad objektet hedder, når du læser det ind.
Hvornår bruger du hvad? (Parquet, RDS, SAS, CSV)
De tre formater du faktisk arbejder med i hverdagen:
| Filtype | Bruges til |
|---|---|
| Parquet | De store registre (BEF, LPR, LMDB …). Du indlæser dem dovent og filtrerer, før du henter data. |
| RDS | Dine egne mellemresultater - datasæt du gemmer fra ét script og genindlæser i det næste. |
| SAS | Formateringstabeller og rå registerdata, der endnu ikke er konverteret til parquet. |
RDS er R’s eget format. Det er hurtigt, kompakt og bevarer alle R-egenskaber (datatyper, faktorniveauer, kolonnenavne) perfekt. Arbejder du med en pipeline af scripts - fx et script der bygger din kohorte og et andet der trækker diagnoser - gemmer du resultatet fra script 1 som .rds, så script 2 kan læse det ind og fortsætte derfra, uden at køre alt om igen.
SAS - til formateringstabeller og ikke-konverteret registerdata:
library(haven)
df <- read_sas("E:/rawdata/[projektnummer]/lpr_adm2018.sas7bdat")Indlæsning af store SAS-filer er meget langsomt - det er netop derfor data på DST er konverteret til parquet. Brug kun SAS til formateringstabeller og filer uden parquet-version.
CSV - til eksport af færdige tabeller (fx ved hjemsendelse):
library(readr)
write_csv(min_tabel, "output/tabel1.csv")Gem aldrig rå registerdata som CSV - kun aggregerede resultater. Se Fase 14 - Eksport og hjemsendelse for reglerne.
Konvertér SAS-filer til Parquet
De fleste projekter på DST modtager registre som SAS-filer (.sas7bdat). Inden du kan bruge dem med open_dataset() og doven evaluering, skal de konverteres til Parquet én enkelt gang. Derefter bruger du dem præcis som alle andre registre.
Relevant for de fleste uden for DARTER. Arbejder du på et projekt hvor registrene ikke allerede er konverteret til parquet, er dette trin nødvendigt inden du kan køre udtræk. Gøres én gang per register - herefter gælder det normale udtræksmønster.
Hvorfor Parquet er det værd (SAS vs Parquet)
| SAS (.sas7bdat) | Parquet | |
|---|---|---|
| Læsetid (1M rækker) | ~30–120 sek | ~1–3 sek |
| Diskplads | Stor | 50–75 % mindre |
| Kræver pakke | haven |
arrow |
| Doven evaluering | Nej - alt ind i RAM | Ja - filter FØR collect |
Anbefalet: konvertér med fastreg
Det anbefalede værktøj er pakken fastreg (dp-next, på CRAN). Den konverterer SAS-registre til Parquet (partitioneret efter år) og lader dig læse dem ind igen via registrets navn.
Brug fastregs egen vejledning til selve konverteringskoden. De præcise kommandoer er dokumenteret - og holdes opdateret af teamet - i fastregs Getting started-vignette. Vi linker til det relevante afsnit nedenfor frem for at gengive kode, der kan blive forældet. Du installerer den én gang med install.packages("fastreg") og peger den på dine rådata- og output-mapper, som vist der.
Konvertér én fil
Skal du kun konvertere én SAS-fil, så brug fastregs convert()-funktion - den skriver ét enkelt register til Parquet. Se Getting started-vignetten for det præcise kald.
Konvertér flere filer på én gang
Skal du konvertere et helt workspace, anbefaler fastreg-teamet dens targets-pipeline: use_template() kopierer en klar-til-brug pipeline, der konverterer alle dine registre parallelt - reproducerbart, og genkørbart når et register opdateres. Se Converting multiple registers in parallel.
Hvis fastreg ikke er tilgængelig på dit projekt: konvertér manuelt med haven + arrow
Kan du ikke installere fastreg, kan du konvertere et enkelt register selv. Det er grundlæggende det, fastreg gør under motorhjelmen:
library(haven) # læs SAS-fil
library(arrow) # skriv Parquet
sas_fil <- "E:/rawdata/[projektnummer]/rawdata/mit_register.sas7bdat"
parq_sti <- "E:/workdata/[projektnummer]/cleaned-data/parquet-registers/mit_register/"
# 1. Læs SAS-filen ind i R
df <- read_sas(sas_fil) # læser hele filen ind i RAM - vi kalder den "df", men du kan bruge et hvilket som helst navn
# 2. Standardisér kolonnenavne
df <- df %>% rename_with(tolower)
# 3. Skriv som Parquet
dir.create(parq_sti, recursive = TRUE, showWarnings = FALSE)
write_parquet(df, file.path(parq_sti, "mit_register.parquet"))
# 4. Verificér - åbn det dovent ligesom alle andre registre
open_dataset(parq_sti) %>% glimpse()Læs kun det du har brug for. Allerede inden du konverterer kan du spare RAM ved at begrænse, hvad der læses ind:
read_sas()(haven) tagercol_select = c(pnr, alder, civst)(vælg kolonner),n_max = 10000(kun de første rækker - godt til test) ogskip =.heaven::import_SAS()(forudinstalleret på DST) er endnu mere effektiv til store filer og kan filtrere på værdier - fxkeep = c("pnr","atc"),where = "..."(filtrér rækker) ellerobs = 1000.
Du kan også konvertere til Parquet (eller .dta) i StatTransfer, som findes på alle servere i det fælles miljø.
Næste skridt
Hvorfor doven indlæsning fungerer, og hvordan collect() virker, er emnet for næste fase.
→ Fase 5 - Udtræk trin for trin
Generel uddybning (på engelsk):
- Import and export i The Epidemiologist R Handbook.
- Arrow i R for Data Science: at læse parquet med
open_dataset()og bruge dplyr direkte på arrow-data - præcis det indlæsningsmønster, denne guide bygger på.