The dscore
package is under development, and not yet publicly available. In order to run this document in RStudio, you need to install the dscore
package from a private Github repository. If you want to do so, please drop a note to Stef van Buuren to getting a proper access key.
This vignettes shows how to estimate the D-score and the D-score SDS, a.k.a. DAZ in an excerpt from the POPS data. This vignettes covers some typical actions needed when estimating D-scores:
The dscore
package has built-in example data from the POPS study, called popsdemo
. The data set is of class tbl_df
from the dplyr
package.
library("dscore")
popsdemo
## # A tibble: 100 x 67
## patid gender gestationalage moment age occ daycor dead Fixateseyes
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 2 30.28571 2 161 1 95 0 0
## 2 1 2 30.28571 3 301 2 236 0 NaN
## 3 1 2 30.28571 4 511 3 443 0 NaN
## 4 1 2 30.28571 5 1008 4 940 0 NaN
## 5 4 1 32.42857 2 140 1 93 0 0
## 6 4 1 32.42857 3 231 2 184 0 NaN
## 7 4 1 32.42857 4 420 3 368 0 NaN
## 8 4 1 32.42857 5 763 4 716 0 NaN
## 9 5 1 31.57143 2 147 1 94 0 0
## 10 5 1 31.57143 3 238 2 185 0 NaN
## # ... with 90 more rows, and 58 more variables: Reactstospeech <dbl>,
## # Movesbotharmsequallyasmuch <dbl>, Movesbothlegsequallyasmuch <dbl>,
## # Liftschin <dbl>, Smilesback <dbl>, Followswitheyesandhead <dbl>,
## # Handsopennowandthen <dbl>, Looksatownhands <dbl>,
## # Vocalizesresponsively <dbl>,
## # Remainspositionedwhenliftedunderthearmpits <dbl>,
## # Holdsheadupfortyfivedegreesinproneposition <dbl>,
## # Handsplayinginmidline <dbl>, Graspstoywithinreach <dbl>,
## # Noheadlagwhenpulledtosittingposition <dbl>, Turnsheadtosound <dbl>,
## # Whenliftedverticallylegsbendedortrampling <dbl>,
## # Holdsheadupninetydegreesinproneposition <dbl>,
## # Transferstoyeasilyhandtohand <dbl>,
## # Picksuponesmalltoythensecond <dbl>, Playswithbothfeet <dbl>,
## # Rollsfrompronetosupineandback <dbl>,
## # Holdsheadupinsittingposition <dbl>, Sitswithstretchedlegs <dbl>,
## # Saysdadababaorgaga <dbl>, Sitswithoutsupport <dbl>,
## # Picksupcrumbbetweenthumbandindexfinger <dbl>, Crawls <dbl>,
## # Pullshimselftostandingposition <dbl>, Wavesbyebye <dbl>,
## # Jabbering <dbl>, Getscubeintoandoutofbox <dbl>,
## # Playsgiveandtake <dbl>, Crawlswithbellyliftedofheground <dbl>,
## # Walkswhileholdingfurniture <dbl>, Understandssomesimplewords <dbl>,
## # Usestwowords <dbl>, Makestoweroftwocubes <dbl>, Exploresroom <dbl>,
## # Usesthreewords <dbl>, Identifiestwonamedobjects <dbl>,
## # Walksonitsown <dbl>, Throwsballwithoutfalling <dbl>,
## # Makestowerofthreecubes <dbl>, Imitateseverydayactivities <dbl>,
## # Drinksfromcup <dbl>, Makestwowordsentences <dbl>,
## # Putsballinboxwhenasked <dbl>, Squats <dbl>, Walkswell <dbl>,
## # Makestowerofsixcubes <dbl>, Putsroundfigureintoplace <dbl>,
## # Takesoffaclothshoesocktrousers <dbl>, Eatswithspoonwithouthelp <dbl>,
## # CallsitselfbynameorI <dbl>, Identifiespicturesinbook <dbl>,
## # Kicksballaway <dbl>, dscore <dbl>, daz <dbl>
class(popsdemo)
## [1] "tbl_df" "tbl" "data.frame"
nrow(popsdemo)
## [1] 100
The are 25 children and 4 time points.
# 25 children, 4 time points per child
length(unique(popsdemo$patid))
## [1] 25
The item scores that form the test are located in columns 9-65.
test <- 9:65
These names of the columns need to be matched against one of the lexicons in the item bank. The built-in lexicons are:
names(itembank)[1:6]
## [1] "lex.dutch1996" "lex.dutch2005" "lex.dutch1983" "lex.SMOCC"
## [5] "lex.GHAP" "lex.jam"
We first need to find out a proper lexicon for the data. For the POPS data, the closest lexicon is . Let us check the variable names in POPS with the item labels in the item bank.
itemset <- !is.na(itembank$lex.dutch1983)
cbind(names(popsdemo)[test], itembank[itemset, c("lex.dutch1983", "labelEN", "tau")])
## names(popsdemo)[test] lex.dutch1983
## 1 Fixateseyes v1
## 2 Reactstospeech v2
## 3 Movesbotharmsequallyasmuch v3
## 6 Movesbothlegsequallyasmuch v4
## 9 Liftschin v5
## 10 Smilesback v6
## 11 Followswitheyesandhead v7
## 14 Handsopennowandthen v8
## 17 Looksatownhands v9
## 18 Vocalizesresponsively v10
## 19 Remainspositionedwhenliftedunderthearmpits v11
## 20 Holdsheadupfortyfivedegreesinproneposition v12
## 23 Handsplayinginmidline v13
## 24 Graspstoywithinreach v14
## 27 Noheadlagwhenpulledtosittingposition v15
## 28 Turnsheadtosound v16
## 31 Whenliftedverticallylegsbendedortrampling v17
## 34 Holdsheadupninetydegreesinproneposition v18
## 35 Transferstoyeasilyhandtohand v19
## 36 Picksuponesmalltoythensecond v20
## 37 Playswithbothfeet v21
## 40 Rollsfrompronetosupineandback v22
## 41 Holdsheadupinsittingposition v23
## 42 Sitswithstretchedlegs v24
## 43 Saysdadababaorgaga v25
## 45 Sitswithoutsupport v26
## 46 Picksupcrumbbetweenthumbandindexfinger v27
## 49 Crawls v28
## 50 Pullshimselftostandingposition v29
## 51 Wavesbyebye v30
## 52 Jabbering v31
## 54 Getscubeintoandoutofbox v32
## 57 Playsgiveandtake v33
## 58 Crawlswithbellyliftedofheground v34
## 59 Walkswhileholdingfurniture v35
## 60 Understandssomesimplewords v36
## 61 Usestwowords v37
## 63 Makestoweroftwocubes v38
## 66 Exploresroom v39
## 67 Usesthreewords v40
## 68 Identifiestwonamedobjects v41
## 69 Walksonitsown v42
## 70 Throwsballwithoutfalling v43
## 74 Makestowerofthreecubes v44
## 77 Imitateseverydayactivities v45
## 78 Drinksfromcup v46
## 79 Makestwowordsentences v47
## 80 Putsballinboxwhenasked v48
## 81 Squats v49
## 82 Walkswell v50
## 84 Makestowerofsixcubes v51
## 85 Putsroundfigureintoplace v52
## 86 Takesoffaclothshoesocktrousers v53
## 87 Eatswithspoonwithouthelp v54
## 88 CallsitselfbynameorI v55
## 89 Identifiespicturesinbook v56
## 90 Kicksballaway v57
## labelEN tau
## 1 Eyes Fixate 5.4
## 2 Reacts when spoken to 1.7
## 3 Moves arms equally well -2.2
## 6 Moves legs equally well -1.9
## 9 Lifts chin off table for a moment 5.2
## 10 Smiles in response 11.3
## 11 Follows with eyes and head 14.5
## 14 Hands occasionally open 16.5
## 17 Watches own hands 20.7
## 18 Vocalizes in response 14.5
## 19 Stays suspended when lifted under armpits 15.8
## 20 Lifts head to 45 degrees in prone position 20.0
## 23 Plays with hands in midline 28.2
## 24 Supine position: grasps object within reach 29.9
## 27 Reactions if pulled to sitting 26.0
## 28 Turns head to sound 31.1
## 31 Flexes or stomps legs while being swung 25.7
## 34 Looks around to side with angle face-table 90 degrees 27.8
## 35 Passes cube from hand to hand 36.0
## 36 Holds cube, grasps another one with other hand 36.5
## 37 Plays with both feet 33.2
## 40 Rolls over, back and forth 34.7
## 41 Balances head well while sitting 32.5
## 42 Sits on buttocks while legs stretched 34.9
## 43 Says "dada", "baba", or "gaga" 36.0
## 45 Sits in stable position, without support 40.0
## 46 Picks up pellet between thumb and index finger 43.1
## 49 Crawls forward, abdomen on the floor 43.1
## 50 Pulls up to standing position 44.3
## 51 Waves "bye bye" 43.1
## 52 Jabbering while playing (M; can ask parents) 40.9
## 54 Puts cube in and out of a box 46.0
## 57 Plays "give and take" 46.5
## 58 Crawls, with belly lifted off the ground (M; can ask parents) 46.1
## 59 Walks along 46.1
## 60 Understands some simple words (M; can ask parents) 45.7
## 61 Says 2 "sound-words" with comprehension 50.1
## 63 Builds tower of two cubes 56.4
## 66 Explores environment 46.9
## 67 Says 3 "words" 53.2
## 68 Identfies (point / graps) two mentioned objects 55.4
## 69 Walks on his/her own 51.9
## 70 Throws ball without falling down 56.0
## 74 Builds tower of three cubes 59.2
## 77 Imitates others 52.3
## 78 Drink from cup by him/herself (M; can ask parents) 58.5
## 79 Says "sentences"of 2 words 60.2
## 80 Puts ball in box when asked 57.8
## 81 Squats or bends to pick up things 55.3
## 82 Walks well without help 55.5
## 84 Builds tower of 6 cubes 62.6
## 85 Places round form in form-box 60.3
## 86 Undresses himself 60.6
## 87 Eats with spoon without help (M; can ask parents) 58.5
## 88 Refers to self using "me" or "I" 61.7
## 89 Points at 5 pictures in the book 62.2
## 90 Kicks ball 64.2
In this case, we are lucky that all item names from the source data and the item bank match up exactly. In general, we will need to map carefully the names in the dataset to the names in the item bank. For POPS, we may take out the relevant parts of the item bank as
ib <- itembank[itemset,c("lex.dutch1983", "lex.GHAP", "labelEN", "tau")]
head(ib, 3)
## lex.dutch1983 lex.GHAP labelEN tau
## 1 v1 GSFIXEYE Eyes Fixate 5.4
## 2 v2 GSRSPCH Reacts when spoken to 1.7
## 3 v3 GSMARM Moves arms equally well -2.2
From here on, we will work in the GHAP lexicon. Renaming the source data is now done by
names(popsdemo)[test] <- as.character(ib$lex.GHAP)
The source data has now names that are recognized in the itembank. To check this, find the difficulties for each item by the gettau()
function:
gettau(names(popsdemo)[test])
## GSFIXEYE GSRSPCH GSMARM GSMLEG GSLFCHIN GSSMILE GSFEYE GSHOPEN
## 5.4 1.7 -2.2 -1.9 5.2 11.3 14.5 16.5
## GSLKHN GSVOCAL GSRP GSHH45 GSHPLAYM GSGRP GSNOHLAG GSTHEAD
## 20.7 14.5 15.8 20.0 28.2 29.9 26.0 31.1
## GSLBEND GSHH90 GSTTOY GSPTOY GSPLFT GSROLLS GSHHSIT GSSITST
## 25.7 27.8 36.0 36.5 33.2 34.7 32.5 34.9
## GSSAYS GSSITWS GSPICK GSCRAWL GSPULLST GSWAVES GSJABBER GSGETC
## 36.0 40.0 43.1 43.1 44.3 43.1 40.9 46.0
## GSPLAYGT GSCRBLY GSWALKS GSSIMPLE GSTWOWRD GSMK2CB GSEXPLR GSTHRWRD
## 46.5 46.1 46.1 45.7 50.1 56.4 46.9 53.2
## GSIDOBJ GSWLKOWN GSTBALL GSMK3CB GSIMITAT GSDRNKCP GSTWOSEN GSPUTBAL
## 55.4 51.9 56.0 59.2 52.3 58.5 60.2 57.8
## GSPKSQ GSWLKWH GSMKTW6 GSPUTFIG GSTKCLO GSEATSPN GSREFER GSID5OBJ
## 55.3 55.5 62.6 60.3 60.6 58.5 61.7 62.2
## GSKIK
## 64.2
The dscore()
function takes vectors of item scores, item names and ages. Rearringing the data makes it easy to extract the relevant vectors. We need to create a data set with the following variables: patid
, moment
, age
, daycor
, item
and score
, and select only the rows where we have an observed score.
library("tidyr")
library("dplyr")
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
data <- popsdemo %>%
select(patid, moment, age, daycor, GSFIXEYE:GSKIK) %>%
gather(items, scores, GSFIXEYE:GSKIK, na.rm = TRUE) %>%
mutate(scores = 1 - scores) %>%
arrange(patid, moment)
## Warning: attributes are not identical across measure variables;
## they will be dropped
data
## # A tibble: 1,385 x 6
## patid moment age daycor items scores
## <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
## 1 1 2 161 95 GSFIXEYE 1
## 2 1 2 161 95 GSRSPCH 1
## 3 1 2 161 95 GSMARM 1
## 4 1 2 161 95 GSMLEG 1
## 5 1 2 161 95 GSLFCHIN 1
## 6 1 2 161 95 GSSMILE 1
## 7 1 2 161 95 GSFEYE 1
## 8 1 2 161 95 GSHOPEN 1
## 9 1 2 161 95 GSLKHN 1
## 10 1 2 161 95 GSVOCAL 1
## # ... with 1,375 more rows
There are nrow(data)
records with a nonmissing item score. Note also that the item scores have been reversed, as POPS uses a zero for a PASS, and a one for a FAIL.
For illustration, let us first calculate the D-score of the first child. There are 75 scores for this child, spread over four time points. This is a preterm child, so we correct calener age for gestational age as in daycor
:
child1 <- filter(data, patid == 1)
scores <- child1$scores
items <- as.character(child1$items)
ages <- round(child1$daycor/365.25, 4)
# calculate dscore and daz for each time point for given child
(d <- dscore(scores, items, ages))
## 0.2601 0.6461 1.2129 2.5736
## 25.25 42.73 55.42 70.97
daz(d)
## 0.2601 0.6461 1.2129 2.5736
## 0.159 0.920 0.788 0.595
If desired, one may also back-calculate the D-score from the standard deviation score by
zad(daz(d))
## 0.2601 0.6461 1.2129 2.5736
## 25.25 42.73 55.42 70.97
If we specify the child identifier as a by-group variable, we may calculate the D-score and DAZ for all children by
# use age corrected for gestational age
data <- data.frame(data)
data$ages <- round(data$daycor/365.25, 4)
# calculate D-score and DAZ
ds <- split(data, data$patid)
dl <- parallel::mclapply(ds, FUN = dscore)
dazl <- lapply(dl, FUN = daz)
df <- data.frame(
patid = rep(as.numeric(names(dl)), times = unlist(lapply(dl, length))),
ages = as.numeric(unlist(lapply(dl, names))),
dscore = as.numeric(unlist(dl)),
daz = as.numeric(unlist(dazl)))
head(df)
## patid ages dscore daz
## 1 1 0.2601 25.25 0.159
## 2 1 0.6461 42.73 0.920
## 3 1 1.2129 55.42 0.788
## 4 1 2.5736 70.97 0.595
## 5 4 0.2546 23.15 -0.416
## 6 4 0.5038 31.75 -1.202
Finally, in order to do further analyses, we need to put the estimated D-score and DAZ back into the source data.
# merge dscore and daz into popsdemo data
popsdemo$ages <- round(popsdemo$daycor/365.25, 4)
popsdemo <- merge(popsdemo, df, all.x = TRUE)
head(select(popsdemo, patid, moment, ages, dscore, daz))
## patid moment ages dscore daz
## 1 1 2 0.2601 25.26 0.163
## 2 1 3 0.6461 42.72 0.916
## 3 1 4 1.2129 55.44 0.794
## 4 1 5 2.5736 70.82 0.541
## 5 4 2 0.2546 23.15 -0.416
## 6 4 3 0.5038 31.75 -1.202