Kombineret boxplot og beeswarm grafer i R

Her den anden dag ville jeg gerne lave en såkaldt boxplot graf for at fremstille lidt data. Her er hvad jeg endte med:

Hvordan laver man nu det?

Jeg har før leget med open-source programmet R. Det er gratis og indeholder temmelig omfattende statistiske og grafiske egenskaber.

I dette eksempel tager jeg udgangspunkt i offentlig tilgængelig data fra Vanderbilt Univeristy om prostatakræft. Datasættet kan hentes her.

Advarsel: jeg er ikke programmør, og der er sikkert mange mere korrekte måder, at gøre alle disse ting på, men omvendt viser jeg det så simpelt her, at alle kan gøre det. Yderligere: man kan ikke drage nogle videnskabelige konklusioner fra eksemplerne her.

Gennemse data

Man kan få data ind i R på mange måder (beskrevet i stor detalje her) men det letteste er nu, at starte med at åbne bruge Excel til at ordne dine data og herefter gemme filen som en komma-separeret fil (en såkaldt csv fil).

Det er en god ide at checke filen igennem. Fx vil jeg gerne sammenligne ”sz” kolonnen med ”sg” kolonnen. Sz er størrelsen af tumoren og sg er en kombineret værdi af tumorens stadie, baseret på den kliniske undersøgelse og en vævprøve fra tumoren. Er der med andre ord en sammenhæng mellem størrelsen af prostata og alvoren af tumoren? Det er vigtigt at kigge rækkerne igennem – for en del patienter er der ikke data i de to rækker og det får R til at opføre sig underligt. For nemhedens skyld har jeg derfor bare slettet disse og gemt filen i csv-formattet.

Prostata.csv på nu gemt på mit skrivebord. Inden vi går rigtigt i gang er det en god ide, at åbne filen med et simpelt tekstprogram som TextEdit på Mac eller Notepad i Windows og gennemse den – fx gemmer min version af Excel data med et semikolon (;) som separator, ikke et komma. Det er vigtigt at vide når vi skal indlæse data i R.

Her kan man også se, at den øverste linie indeholder ”kolonne-navnene”, og de resterende linier indeholder data for godt og vel 500 patienter. En patient pr. linie. På Vandebilts hjemmeside kan man se en oversigt over hvad de forskellige forkortelser i filen står for.

Indlæs data i R

Herefter skal R startes op. Jeg vil anbefalde at du laver et nyt dokument og skriver alt din kode ind i denne fil og herefter copy-paster koden over i selve R programmet. Koden eksekveres bare ved at trykke på enter.

Vores datasæt kan indlæses i R med:

prostata <- read.table("/Users/Barnkob/Desktop/prostate.csv",
as.is = TRUE,
header = TRUE,
sep = ";",
row.names = 1
)

Her indlæses filens værdier til ”prostata” med funktionen read.table. <- er måden hvorpå vi binder data til en variable. Funktionen read.table laver selve arbejdet og læser vores fil – den har forskellige kommandoer, der sættes i parentesen og som man kan ændre på. Kommandoerne er adskilte af kommaer.

Den første kommando fortæller hvor filen er gemt. Header = TRUE fortæller funktionen at den første linie i csv-filen er kolonne-navnene. Sep = ; fortæller at de enkelte data i filen er afskilt af et semikolon – her kunne du også skrive , (komma) eller hvad der ellers adskiller data. Row.names = 1 fortæller at den første række (row) skal være den enkelte rækkes id. Hvis du vil vide mere om read.table funktionen kan du i R skrive:

help(read.table)

Prøv nu at skriv ”prostata”. I vinduet burde der nu komme en liste med alle informationerne i.

Hvis du bare vil have data fra en kolonne kan du skrive prostata$sz fx. Hvis du bare vil se de første fem værdier, kan du skrive prostata$sz[1:5].

Grafer

Nu da vi har indlæst data i R, er det let at laver grafer med det. Prøv fx at skrive:

plot(prostata$sz ~ prostata$sg)

Beeswarm er en tillæggesfunktion til R, der er lavet af Aron Eklund fra DTU. Første gang du bruger den skal den installeres med:

install.packages("beeswarm")

Du bliver nu bedt om en server at hente funktionen ned med. Vælg en i Danmark eller en langt væk. Det er vist godt det samme.

Først gang vi bruger funktionen, skal den indlæses i R med funktionen:

library(beeswarm)

Nu kan vi lave en ”beeswarm” med vores data:

beeswarm(prostata$sz ~ prostata$sg,
data = prostata,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = 'Stoerrelse og stadie',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)

Beeswarm
Beeswarm

I R kan man koble flere forskellige grafer ved at indlæse en graf-funktion, der har kommandoen ”add = TRUE” tilføjet. Så nu kan vi indlæse boxplot funktionen med samme data, således at hele koden ser således ud:

beeswarm(prostata$sz ~ prostata$sg,
data = prostata,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = 'Stoerrelse og stadie',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)
boxplot(prostata$sz ~ prostata$sg,
data = prostata,
add = TRUE
)

Grafen kommer til at se således ud:

Beeswarm kombineret med boxplot
Beeswarm kombineret med boxplot. Er der en sammenhæng mellem størrelse og stadie her?

Subgrupper

Men datasættet er faktisk lavet på patienter der alle har modtaget behandling. I rx kolonnen kan man se om patienterne har fået placebo (altså bare en sukkerpille), 0.2, 1 eller 5 mg østrogen-behandling.

Siden jeg bare er interesseret i den ubehandlet udvikling af prostata-cancer, vil jeg prøve at lave en subgruppe med alle de patienter der har modtaget placebo, og dermed ingen behandling. Det gøres således:

prostata.sub <- prostata[prostata$rx == "placebo", ]

Nu kan vi køre graf-funktionerne fra før, bare med prostata.sub i stedet for prostata. Resultatet bliver således:

Subgruppe der ikke har modtaget behandling
Subgruppe der ikke har modtaget behandling

Du kan læse mere om hvordan man laver subgrupper på denne hjemmeside.

Er der så en sammenhæng mellem størrelse og alvor af tumoren? Det er ikke muligt at vide alene med disse grafer – for at svare på det må vi istedet bruge nogle af de statistiske funktioner R har, men det bliver i et andet indlæg.

Men lad os lege med en enkelt overvejelse her: nemlig, at prostata’s størrelse vokser med alderen. Lad os inddele vores subgruppe i forskellige aldersgrupper og vise dem samlet.

Vi starter med at lave forskellige subgrupper:

prostata.sub0til60 <- prostata.sub[prostata.sub$age < 61, ]
prostata.sub61til70 <- prostata.sub[prostata.sub$age > 60 & prostata.sub$age < 71, ]
prostata.sub71til80 <- prostata.sub[prostata.sub$age > 70 & prostata.sub$age < 81, ]
prostata.sub81til100 <- prostata.sub[prostata.sub$age > 80 & prostata.sub$age < 101, ]

For at skabe et overblik, lad os fremstille alle grupper i den samme graf. Det gøres således:

par(mfrow=c(2,2))
beeswarm(prostata.sub0til60$sz ~ prostata.sub0til60$sg,
data = prostata.sub0til60,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = '0 til 60 aar',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)
boxplot(prostata.sub0til60$sz ~ prostata.sub0til60$sg,
data = prostata.sub0til60,
add = TRUE
)
beeswarm(prostata.sub61til70$sz ~ prostata.sub61til70$sg,
data = prostata.sub61til70,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = '61 til 70 aar',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)
boxplot(prostata.sub61til70$sz ~ prostata.sub61til70$sg,
data = prostata.sub61til70,
add = TRUE
)
beeswarm(prostata.sub71til80$sz ~ prostata.sub71til80$sg,
data = prostata.sub71til80,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = '71 til 80 aar',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)
boxplot(prostata.sub71til80$sz ~ prostata.sub71til80$sg,
data = prostata.sub71til80,
add = TRUE
)
beeswarm(prostata.sub81til100$sz ~ prostata.sub81til100$sg,
data = prostata.sub81til100,
method = "square",
log = FALSE,
pch = 16,
col = rainbow(11),
main = '81 til 100 aar',
xlab = 'Stadie',
ylab = 'Stoerrelse af primaere tumor'
)
boxplot(prostata.sub81til100$sz ~ prostata.sub81til100$sg,
data = prostata.sub81til100,
add = TRUE
)

Resultatet bliver:

Fire grafer i en
Fire grafer i en

Jeg håber at eksemplerne her har forklaret lidt om hvordan man laver grafer i R (og ikke så meget andet end det).

2 thoughts on “Kombineret boxplot og beeswarm grafer i R

  1. Fint post om R, Mike; har selv brugt det til at lave meta analyse til min bacheloropgave. Jeg ville bare lige anbefale RStudio, som er et moderne programmeringsmiljø for R som findes for Linux, Windows og Mac. Det gør det en del nemmere at bruge R når man ikke er 100% nørd, siden der også er grafisk adgang til mange af funktionerne, ens dataset direkte bliver vist som tabeller efter de er blevet indlæst og alle definere variabler bliver listet. Check det ud: http://rstudio.org/

Skriv et svar

Din e-mailadresse vil ikke blive offentliggjort. Krævede felter er markeret med *