4 Databehandling
Databehandling er et stort emne. Her vil jeg begrænse mig til at beskrive de vigtigste principper, som er nødvendige til at omsætte rådata til indikatorværdier i tabeller og grafer.
Målet for databehandling og -analyse er troværdige og reproducerbare analyser, hvor den samme analyse på samme data altid giver samme resultat. En analyse er i sagens natur kun troværdig, hvis hvert trin i analysen kan beskrives tilstrækkelig detaljeret til at andre vil kunne gentage analysen og opnå samme resultat. En analyse er kun reproducerbar, hvis analysen kan automatiseres, så den kan gennemføres uden menneskelig indgriben (udover at “trykke på knappen”).
Disse to principper udelukker brug af peg-og-klik- og klippe-klistre-teknikker. Derfor bør databehandling og -analyse så vidt muligt ske ved programmering, hvor hvert eneste trin i processen er skrevet, og dermed dokumenteret, i programkode, som kan afvikles af en computer.
Jeg anbefaler, at alle, som arbejder med data mere end sjældent, lærer sig grundlæggende databehandling med et programmeringssprog. Dem findes der mange af. På de danske universiteter lærer man fortrinvis enten SAS, STATA, R eller Python. Jeg foretrækker programmeringssproget R [6], som er et af de mest benyttede programmer i verden til databehandling, statistik og grafik. R er open source, dvs. frit tilgængeligt og gratis, og enhver der ønsker det, har mulighed for at bidrage til udviklingen af R. Et godt sted at begynde er R for Data Science [7].
4.1 Fem fundamentale funktioner
Jeg vil ikke give konkrete anvisninger på, hvordan man foretager den ene eller anden dataoperation i R eller andre programmer men i stedet give en generisk beskrivelse af de fem grundlæggende dataoperationer, som indgår i næsten enhver dataanalyse:
Filtrere: udvælge poster (rækker)
Selektere: udvælge variable (kolonner)
Transformere: udregne afledte variable eller ændre eksisterende variable
Aggregere: udregne sammendrag (fx sum, gennemsnit, spredning) af variable på tværs af poster
Sortere: ændre posternes rækkefølge
De fem operatoner forudsætter, at data er velstrukturerede og opstillet pænt i rækker og kolonner som beskrevet i forrige kapitel.
I dette og næste kapitel benytter vi et datasæt fra en spørgeskemaundersøgelse om voksne personers helbredsstatus. I undersøgelsen indgik i alt 2742 personer. For overskuelighedens skyld benytter jeg i de følgende eksempler kun data fra 12 tilfældigt udvalgte personer (Tabel 4.1).
id | alder | koen | hoejde | vaegt | ryger | helbred |
---|---|---|---|---|---|---|
1836 | 29 | Mand | 180 | 84 | FALSE | Meget godt |
2486 | 39 | Kvinde | 167 | 77 | TRUE | Nogenlunde |
2098 | 75 | Mand | 180 | 92 | TRUE | Meget godt |
794 | 37 | Mand | 183 | 75 | FALSE | Meget godt |
2545 | 83 | Mand | 167 | 103 | FALSE | Dårligt |
326 | 37 | Mand | 189 | 90 | FALSE | Godt |
991 | 72 | Mand | 179 | 88 | TRUE | Nogenlunde |
111 | 23 | Kvinde | 176 | 67 | TRUE | Meget godt |
63 | 64 | Mand | 180 | 90 | TRUE | Meget dårligt |
551 | 54 | Kvinde | 172 | 99 | FALSE | Nogenlunde |
2253 | 39 | Mand | 180 | 84 | FALSE | Godt |
1666 | 74 | Kvinde | 163 | 77 | FALSE | Godt |
4.1.1 Filtrere
Ved filtrering udvælger man poster (rækker) fra data. Rådata omfatter typisk flere poster, end dem, som skal med i indikatoropgørelsen. Derfor skal data filtreres til kun at indeholde de nødvendige poster. Filtrering foregår ved hjælp af logiske kriterier, fx koen = ‘Kvinde’ eller hoejde > 170, som appliceres på hele datasættet.
Resultatet af en filteroperation er et nyt, reduceret datasæt, som indeholder de samme variable men kun de poster fra rådata, som opfylder kriterierne (Tabel 4.2).
id | alder | koen | hoejde | vaegt | ryger | helbred |
---|---|---|---|---|---|---|
111 | 23 | Kvinde | 176 | 67 | TRUE | Meget godt |
551 | 54 | Kvinde | 172 | 99 | FALSE | Nogenlunde |
4.1.2 Selektere
Ved selektion udvælger man variable (kolonner) fra data. Udvælgelse af variable har sjældent indflydelse på selve analysen men kan være nyttig af både kosmetiske og praktiske hensyn (Tabel 4.3).
koen | hoejde | vaegt |
---|---|---|
Mand | 180 | 84 |
Kvinde | 167 | 77 |
Mand | 180 | 92 |
Mand | 183 | 75 |
Mand | 167 | 103 |
Mand | 189 | 90 |
Mand | 179 | 88 |
Kvinde | 176 | 67 |
Mand | 180 | 90 |
Kvinde | 172 | 99 |
Mand | 180 | 84 |
Kvinde | 163 | 77 |
Det er ikke ualmindeligt, at data fra store kliniske datasystemer indeholder hundredvis eller ligefrem tusindvis af variable, som selvsagt gør data helt uoverskuelige og meget tunge at arbejde med. Men selv ved mindre datasæt, er det god praksis kun at medtage de nødvendige variable i sin analyse.
4.1.3 Transformere
Ved transformation omdanner man en variabel, fx centimeter til meter eller minutter til timer. Man kan også danne helt nye variable ud fra eksisterende variable, fx alder fra fødselsdato eller kropsmasseindeks (BMI) fra højde og vægt (Tabel 4.4).
koen | hoejde | vaegt | bmi |
---|---|---|---|
Mand | 180 | 84 | 25.9 |
Kvinde | 167 | 77 | 27.6 |
Mand | 180 | 92 | 28.4 |
Mand | 183 | 75 | 22.4 |
Mand | 167 | 103 | 36.9 |
Mand | 189 | 90 | 25.2 |
Mand | 179 | 88 | 27.5 |
Kvinde | 176 | 67 | 21.6 |
Mand | 180 | 90 | 27.8 |
Kvinde | 172 | 99 | 33.5 |
Mand | 180 | 84 | 25.9 |
Kvinde | 163 | 77 | 29.0 |
4.1.4 Aggregere
At aggregere betyder at slå poster sammen så flere rækker bliver til én række. Man aggregerer fx, når man udregner gennemsnitsværdien af en variabel på tværs af alle poster. Ofte er man interesseret i at aggregere inden for grupper, fx gennemsnitshøjden eller andelen af rygere for hhv. mænd og kvinder (Tabel 4.5).
koen | N | andel_rygere | middelhoejde | middelvaegt |
---|---|---|---|---|
Mand | 8 | 0.38 | 179.8 | 88.2 |
Kvinde | 4 | 0.50 | 169.5 | 80.0 |
4.1.5 Sortere
Ligesom selektion har sortering ofte mest kosmetisk betydning. Man sorterer posterne efter værdien af en eller flere variable, typisk tid og sted, eller kategoriske variable, som bliver brugt til aggregering (Tabel 4.6).
id | alder | koen | hoejde | vaegt | ryger | helbred |
---|---|---|---|---|---|---|
111 | 23 | Kvinde | 176 | 67 | TRUE | Meget godt |
2486 | 39 | Kvinde | 167 | 77 | TRUE | Nogenlunde |
551 | 54 | Kvinde | 172 | 99 | FALSE | Nogenlunde |
1666 | 74 | Kvinde | 163 | 77 | FALSE | Godt |
1836 | 29 | Mand | 180 | 84 | FALSE | Meget godt |
794 | 37 | Mand | 183 | 75 | FALSE | Meget godt |
326 | 37 | Mand | 189 | 90 | FALSE | Godt |
2253 | 39 | Mand | 180 | 84 | FALSE | Godt |
63 | 64 | Mand | 180 | 90 | TRUE | Meget dårligt |
991 | 72 | Mand | 179 | 88 | TRUE | Nogenlunde |
2098 | 75 | Mand | 180 | 92 | TRUE | Meget godt |
2545 | 83 | Mand | 167 | 103 | FALSE | Dårligt |
Selv om sortering ofte kun har til formål at gøre det lettere at læse og overskue data i tabelformat, kan sortering indimellem være nødvendig af hensyn til dataoperationer, som går på tværs af rækker, fx løbende nummerering eller kumuleret sum, hvor værdien i én række afhænger af værdien i den forrige række.
4.2 Fletning af tabeller
I forrige kapitel om dataindsamling argumenterede jeg for det fornuftige i, at strukturere data i flere tabeller. Den omvendte operation er at flette (eng.: join) data fra flere tabeller sammen i én tabel.
Tabellerne i 4.7 rummer gentagne blodtryksmålinger hos tre patienter. Det er smart at opdele databasen i to tabeller, en til patienternes stamoplysninger og en til blodtryksmålingerne. For det første sparer vi plads ved ikke at skulle gentage alle patienternes stamoplysninger for hver enkelt blodtryksmåling. For det andet skal vi kun rette ét sted i én tabel, hvis en patient skifter navn eller adresse.
|
|
Skulle vi på et tidspunkt få behov for at samle alle data i én tabel, er det let at flette de to tabeller via id-variablen.
id | navn | adresse | diastolisk | systolisk | besoeg |
---|---|---|---|---|---|
1 | Fatima Sørensen | Andeby | 66 | 128 | 1 |
1 | Fatima Sørensen | Andeby | 78 | 133 | 2 |
2 | Åge Abdul | Gåserød | 92 | 145 | 1 |
2 | Åge Abdul | Gåserød | 85 | 153 | 2 |
3 | Dennis Khan | Hobbitrup | 87 | 138 | 1 |
4 | Irma Huáng | Hogsmeade | NA | NA | NA |
Tabel 4.8 er resultatet af et såkaldt left join, hvor alle rækkerne i én tabel (patient) kobles med tilhørende rækker i en anden tabel (blodtryk). Hvis en post i den venstre tabel har flere tilknyttede poster i den højre tabel, oprettes tilsvarende flere poster i den flettede tabel. Hvis der findes poster i den venstre tabel, som ingen poster har i den højre tabel, indsættes tomme felter i den flettede tabel.
Der findes andre typer joins, bl.a. right join, inner join og outer join, som adskiller sig fra hinanden på den måde, de håndterer koblingen mellem højre og venstre tabel på.
4.3 Transponering mellem bredt og højt format
Hvis man selv står for dataindsamling, kan man fra begyndelsen designe sin database fornuftigt og bl.a. sørge for at data, som hører naturligt sammen, er struktureret i separate tabeller. Men ofte støder man på data, som allerede er struktureret uhensigtsmæssigt. En af disse udbredte og uhensigtsmæssige måder at strukturere data på er, når data og variabelnavne blandes sammen.
I Tabel 4.9 har man sammenblandet oplysning om variablen (systolisk/diastolisk) med besøgnummeret (1/2) i kolonneoverskrifterne. Ydermere har man struktureret data i bredt format (ligesom i Tabel 3.1), som gør det vanskeligt at arbejde videre med data.
navn | systolisk_1 | diastolisk_1 | systolisk_2 | diastolisk_2 |
---|---|---|---|---|
Fatima Sørensen | 128 | 66 | 133 | 78 |
Åge Abdul | 145 | 92 | 153 | 85 |
Dennis Khan | 138 | 87 |
For at rette op på miseren, må vi først transponere data fra bredt til højt format ved at gøre kolonneoverskrifterne til de, de i virkeligheden er: data (Tabel 4.10).
navn | variabel | blodtryk |
---|---|---|
Fatima Sørensen | systolisk_1 | 128 |
Fatima Sørensen | diastolisk_1 | 66 |
Fatima Sørensen | systolisk_2 | 133 |
Fatima Sørensen | diastolisk_2 | 78 |
Åge Abdul | systolisk_1 | 145 |
Åge Abdul | diastolisk_1 | 92 |
Åge Abdul | systolisk_2 | 153 |
Åge Abdul | diastolisk_2 | 85 |
Dennis Khan | systolisk_1 | 138 |
Dennis Khan | diastolisk_1 | 87 |
Dernæst opdeler vi variabel-kolonnen i to, som repræsenterer hhv., hvad der er målt og ved hvilket besøg, det er målt (Tabel 4.11).
navn | variabel | besoeg | blodtryk |
---|---|---|---|
Fatima Sørensen | systolisk | 1 | 128 |
Fatima Sørensen | diastolisk | 1 | 66 |
Fatima Sørensen | systolisk | 2 | 133 |
Fatima Sørensen | diastolisk | 2 | 78 |
Åge Abdul | systolisk | 1 | 145 |
Åge Abdul | diastolisk | 1 | 92 |
Åge Abdul | systolisk | 2 | 153 |
Åge Abdul | diastolisk | 2 | 85 |
Dennis Khan | systolisk | 1 | 138 |
Dennis Khan | diastolisk | 1 | 87 |
Endlig “retter vi tabellen ud” ved at placere systolisk og diastolisk blodtryk fra samme patient og samme besøg ved siden af hinanden (Tabel 4.12).
navn | besoeg | systolisk | diastolisk |
---|---|---|---|
Fatima Sørensen | 1 | 128 | 66 |
Fatima Sørensen | 2 | 133 | 78 |
Åge Abdul | 1 | 145 | 92 |
Åge Abdul | 2 | 153 | 85 |
Dennis Khan | 1 | 138 | 87 |
Hele operationen har til formål at bringe data på den form, som egner sig bedst til videre bearbejdning og analyse. Og med fare for at gentage mig selv: Det gør vi ved at insistere på, at hver række indeholder én post, hver kolonne indeholder én variabel, og hver celle indeholder én oplysning.