Data science blog #4: depressie in Amerika

Blog, Onderzoek 0 comments

-Door dr. Erik Giltay, psychiater en epidemioloog in het LUMC-

Dit is een blog voor studenten, co-assistenten, arts-assistenten en anderen met interesse voor onderzoek in de psychiatrie. Ik richt me deels op vraagstellingen die met open source databestanden benaderd kunnen worden. Ik zal proberen om de verschillende stappen van het ‘data processing’ proces te laten zien, gebruik makend van R code.

Data opzoeken

Data is steeds vaker verzameld met publiek geld. Die data wordt regelmatig openbaar beschikbaar gesteld, zodat nieuwsgierige onderzoekers daar analyses op kunnen uitvoeren.

Ik zal eerst op zoek gaan naar data over depressie in de USA om te downloaden. Voor Amerikaanse gegevens is NHANES data beschikbaar. Dat is een acronym voor de National Health and Nutrition Examination Survey – CDC. Daar worden met regelmaat enorme steekproeven uit de bevolking aangeschreven die worden uitgenodigd om een gezondheidsonderzoek te ondergaan. Het is beschikbaar in een SAS format, en zo’n dataset kan je met korte sasxport.get-instructies inlezen in R.

library(Hmisc)
NHANES <- sasxport.get("DPQ_I.XPT")
FALSE Processing SAS dataset DPQ_I   ..

Dit is data over de periode van 2015 tot 2016. Het is afkomstig van mensen met een leeftijd van 18 of ouder, afgenomen met een screenings-instrument voor depressie bestaande uit 9 items. Het gaat over de symptomen in de afgelopen 2 weken. De 10e vraag gaat over de impact van deze klachten. De scores van de 9 items loopt van 0 tot 3:

  • 0: “not at all”
  • 1: “several days”
  • 2: “more than half the days”
  • 3: “nearly every day”

Ik ben ten eerste benieuwd of het aantal variabelen dat erin zit klopt, en van de hoeveel mensen data van wie data is verzameld. Dat doe je met de dim instructie (voor ‘dimensions’).

dim(NHANES)
## [1] 5735   11

Dat zijn dus 5735 rijen (mensen) en 11 kolommen (variabelen). Met de glimpse-instructie krijg je een net overzicht van de data.

glimpse(NHANES)
## Observations: 5,735
## Variables: 11
## $ seqn   <int+lbl> 83732, 83733, 83734, 83735, 83736, 83737, 83741, 83...
## $ dpq010 <int+lbl> 0, 1, 0, 1, 1, 0, 0, 0, NA, 0, 0, 0, 0, 1, 1, 1, 1,...
## $ dpq020 <int+lbl> 0, 0, 0, 1, 1, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 2, 1,...
## $ dpq030 <int+lbl> 0, 0, 0, 2, 1, 0, 0, 1, NA, 0, 2, 0, 0, 1, 1, 0, 3,...
## $ dpq040 <int+lbl> 1, 0, 1, 2, 1, 0, 1, 0, NA, 0, 0, 0, 1, 1, 1, 1, 3,...
## $ dpq050 <int+lbl> 0, 1, 0, 1, 3, 0, 0, 0, NA, 0, 0, 0, 0, 1, 1, 0, 2,...
## $ dpq060 <int+lbl> 0, 0, 0, 3, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 2, 1,...
## $ dpq070 <int+lbl> 0, 0, 0, 2, 1, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 1, 1,...
## $ dpq080 <int+lbl> 0, 0, 0, 0, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 2, 1,...
## $ dpq090 <int+lbl> 0, 0, 0, 1, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ dpq100 <int+lbl> 0, 0, 1, 0, 0, NA, 0, 0, NA, NA, 0, NA, 0, 0, 0, 0,...

Summary is ook een eenvoudige instructie die werkt voor de meeste variabelen in de dataframe, om de mediaan, gemiddelde, range, en percentielen te krijgen voor de continue variabelen. Zo krijg je de belangrijkste info voor elke variabele in een handomdraai. Om niet teveel informatie te tonen, selecteer ik alleen de eerste 4 variabelen.

Het is handig om gebruik te maken van de pipe-(%>%)-operator, daarmee stuur je het dataresultaat door naar de volgende bewerking, om zo een ‘pipeline’ van verschillende datamanipulaties uit te kunnen voeren. Dat verbetert de leesbaarheid van je code enorm. Daardoor is het eenvoudiger om complexe datamanipulatie uit te voeren, door de ene eenvoudige instructie de andere te laten volgen. De volgende drie acties worden opeenvolgende uitgevoerd:

  1. neem het dataframe ‘NHANES’
  2. selecteer de kolommen 2 tot en met 5
  3. geef de ‘summary’ statistiek weer van deze 4 variabelen
NHANES %>% 
  select (2:5) %>% 
  summary()
##      dpq010           dpq020           dpq030           dpq040      
##  Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
##  1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000  
##  Median :0.0000   Median :0.0000   Median :0.0000   Median :1.0000  
##  Mean   :0.4225   Mean   :0.3466   Mean   :0.6172   Mean   :0.7836  
##  3rd Qu.:1.0000   3rd Qu.:0.0000   3rd Qu.:1.0000   3rd Qu.:1.0000  
##  Max.   :9.0000   Max.   :7.0000   Max.   :9.0000   Max.   :7.0000  
##  NA's   :571      NA's   :571      NA's   :571      NA's   :573

Dat is equivalent met deze instructie die van binnen naar buiten gelezen moet worden (zonder de ‘pipe’):

summary(select(NHANES,2:5))

Dus er zijn voor de meeste variabelen 571 tot 573 NA’s (not available) ofwel missing values.

Over de eerste variabele staat in het online codebook het volgende geschreven:

DPQ010 – Have little interest in doing things
Variable Name: DPQ010
SAS Label: Have little interest in doing things
English Text: Over the last 2 weeks, how often have you been bothered by the following problems: little interest or pleasure in doing things?
Would you say…

Dus deze vraag gaat over een key symptoom van depressie, namelijk over interesseverlies of gebrek aan plezier.

De antwoordcategorieën zijn:

0 Not at all
1 Several days
2 More than half the days
3 Nearly every day
7 Refused
9 Don’t know

Laat ik daar eens een bar-plot van maken.

NHANES$dpq010 %>% 
  ftable() %>% 
  barplot(main="dpq010: little interest or pleasure", 
    xlab="Antwoordcategorie")

Dat ziet er al aardig uit, maar het is niet zo handig dat je geen informatie krijgt te zien over de labels op de x-as. Deze data kan verder met de Data Documentation, Codebook, and Frequencies worden opgeschoond en gelabeld.

Data opschonen

Ik denk dat het wat beter werkt om de assen om te draaien (met coord_flip()), en het op te maken in het handige data-visualisatie package ggplot2.

NHANES %>%
    mutate (var1 = dpq010 %>% as.factor() %>% 
            recode("0" = "Not at all", "1" = "Several days", 
                   "2" = "More than half the days", 
                   "3" = "Nearly every day", 
                   "7" = "Refused", "9" = "Don't know")) %>% 
   ggplot(aes(var1)) + geom_bar() + 
   coord_flip() + xlab("") +
   ggtitle(attr(NHANES$dpq010, "label")) +
   ylab("Aantal") +
   theme_economist()

Dat wordt inderdaad overzichtelijker. Nu kan ik deze vrij lange instructie 8 maal herhalen voor elke variabele, maar een basisregel in programmeren is om nooit iets te herhalen. Maak daar dan een functie voor en roep die aan. R is een ‘functional programming’ taal. Het is heel eenvoudig om de voorgaande instructie om te zetten in een functie, en deze toe te kennen aan een naam voor die functie met <-. Deze omgekeerde pijl is het toekenningssymbool.

maak_figuur <- function(var_naam) {
   NHANES %>%
    mutate (var1 = NHANES[[var_naam]] %>% as.factor() %>% 
            recode("0" = "Not at all", "1" = "Several days", 
                   "2" = "More than half the days", 
                   "3" = "Nearly every day", 
                   "7" = "Refused", "9" = "Don't know")) %>% 
   ggplot(aes(var1)) + geom_bar() + 
   coord_flip() + xlab ("") +
   ggtitle(attr(NHANES[[var_naam]], "label")) +
   ylab("Aantal") +
   theme_economist()
}

Nu kan voortaan met één korte instructie een figuur worden gemaakt van elk van de 9 variabelen.

maak_figuur("dpq060")

maak_figuur("dpq050")

maak_figuur("dpq090")

In deze aselecte steekproef komt suïcidaliteit dus maar weinig voor.

Data ordenen

Veel data kan op verschillende manieren in een database worden geordend. Om je ‘data-cleaning’ eenvoudig en effectief te laten verlopen is een opgeschoonde dataset nodig. Dit houdt meestal in dat je data in een lang (long) format staat. Zo’n lange gegevensset is gemakkelijk te manipuleren, te modelleren, en te visualiseren. Het heeft een specifieke structuur: elke variabele is een kolom en elke waarneming is een rij.

De volgende twee datasets zijn in essentie hetzelfde, maar de ene is wide (breed) en de ander long (of tall). Deze fictieve tabellen bevatten informatie over depressie die wel of niet aanwezig is in opeenvolgende jaren. Via een enkele spread of een gather instructie zijn deze twee ‘formats’ in elkaar om te zetten.

deelnemer depressie2015 depressie2016 depressie2017
1 1 NA 1
2 0 0 NA
3 1 1 NA
4 0 NA 0
5 0 0 0
deelnemer jaar depressie
1 2015 1
1 2017 1
2 2015 0
2 2016 0
3 2015 1
3 2016 1
4 2015 0
4 2017 0
5 2015 0
5 2016 0
5 2017 0

In de long data-frame zijn geen rijen voor de missing values. In de wide data-frame daarentegen zie je dat sommige deelnemers missing data (NA’s) hebben voor bepaalde jaren.

Hadley Wickham en collega’s hebben veel packages gemaakt met gereedschappen die nodig zijn om deze ‘tidy data’ aan te pakken. Het is vrij eenvoudig om met de functies van de dplyr package deze data te manipuleren en er data manipilatie ermee uit te voeren. Dat pakket zit in de tidyverse. Nadat je eerst dit pakket hebt geinstalleerd, zal je het met de library instructie kunnen activeren voor jouw R-sessie.

install.packages("tidyverse")
library(tidyverse)

Netwerk analyse

Nu kunnen we op deze data bijvoorbeeld een netwerkanalyse doen met het qgraph package. Prof. dr. Denny Borsboom en zijn onderzoeksgroep heeft hier veel over geschreven. Ik zal proberen een netwerk te maken, volgens de online instructies beschreven door Sacha Epskamp in Network Analysis in R Cookbook.

De Spearman’s correlation tabel in de vorm van een heatmap kan gemaakt worden met het package corrplot en toont bijvoorbeeld dat item 9 (‘suïcidaliteit’) hier slechts zwak geassocieerd is met de andere symptomen. Echter hier wordt niet gecorrigeerd (‘partial correlations’) voor andere associaties in het netwerk van symptomen.

library(corrplot)
corMatrix1 <- netwerk %>% 
  cor(use = "pairwise.complete.obs",method = c("spearman")) %>%
  corrplot(method=c("color"), order="hclust",addrect = 5, tl.col = "black")

Zo’n adjustering gebeurt wel in deze netwerkanalyse:

library(qgraph)
corMat <- cor_auto(netwerk)
qgraph(corMat, graph = "pcor", layout = "spring", threshold = "bonferroni",
                     sampleSize = nrow(netwerk), alpha = 0.05)

variabele_naam label
d01 Have little interest in doing things
d02 Feeling down, depressed, or hopeless
d03 Trouble sleeping or sleeping too much
d04 Feeling tired or having little energy
d05 Poor appetite or overeating
d06 Feeling bad about yourself
d07 Trouble concentrating on things
d08 Moving or speaking slowly or too fast
d09 Thought you would be better off dead

Item 6 “Feeling bad about yourself” is dus bijvoorbeeld het sterkst gelinkt aan item 2 “Feeling down, depressed, or hopeless” en aan item 9 “Thought you would be better off dead”.

Een mooi artikel over dit onderwerp van dr. Angélique Cramer, waar ik ook aan meegeschreven heb, is getiteld: Major depression as a complex dynamic system.

Voor commentaar, suggesties, of een interessante vraagstelling:
Contact
Afdeling Psychiatrie, LUMC

Leave a Reply

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.