Programmeertalen hebben alvast dit gemeen met natuurlijke talen: gebruikers ontwikkelen steeds variëteiten die na verloop van tijd kunnen evolueren naar nieuwe dochtertalen.
In R is er momenteel een “variant” genaamd tidyverse(Wickham et al. 2019), dat heel populair geworden is vanwege zijn consistentie en (relatieve) eenvoud. Een van de kernideeën is dat alle datastructuren en output weergegeven worden als tidy data, waarbij elke rij een observatie weergeeft.
Hier maken we een “tibble” – een vereenvoudigede vorm van een dataframe. De code heb ik overgenomen uit het tidyr-vignette. Een vignette is een uitgewerkt voorbeeld van de functionaliteiten van een packages; probeer bvb. vignette("tidy-data").
Een tibble is een vereenvoudigde vorm van een dataframe.
2
een tribble is een tibble die gemaakt wordt aan de hand van rijen. Vergelijk dit met de manier waarop we in het vorige hoofdstuk een dataframe gemaakt hebben en waarbij we vectoren samen hebben gevoegd tot een dataframe. Hier hoeven we enkel rijen in te geven. De tilde \(\sim\) duidt de naam van de variabelen aan.
# A tibble: 4 × 4
name quiz1 quiz2 test1
<chr> <chr> <chr> <chr>
1 Billy <NA> D C
2 Suzy F <NA> <NA>
3 Lionel B C B
4 Jenny A A B
Elke kolom is één variabele, elke rij is één observatie, elke cel is een unieke waarde. Nu zou je kunnen denken dat dit niets speciaals is, maar dezelfde datastructuur wordt consistent gebruikt in doorheen de analyses en output. Dit wordt naderhand duidelijker.
Alhoewel de functionaliteit van base-R door niemand betwist wordt, kiezen veel handboeken en onderzoekers tegenwoordig voor de tidyverse-aanpak. Een bondig hoofdstuk over deze aanpak kan dan ook niet ontbreken.
We openen tidyverse.
library(tidyverse)
Hierdoor openen we meerdere packages tegelijkertijd. In dit hoofdstuk bekijken we twee pakketten in het bijzonder:
tidyr: om het dataformaat te transformeren van het lange naar het wijde dataformaat of omgekeerd.
4.1 Dataset: Falsebeginners
Om de functionaliteiten van dplyr te illustreren gebruiken we de dataset van De Wilde et al. (De Wilde, Brysbaert, and Eyckmans 2019) De dataset is beschikbaar via: https://osf.io/ndr47/. Ik heb voor dit hoofdstuk een aantal variabelen geselecteerd en alles vertaald naar het Nederlands. Table 4.1 biedt een overzicht van de variabelen.
de naam van het bestand dat we openen. Dit bestand moet in dezelfde map zitten als je R-script of Notebook. Hier gebruiken we read.delim () omdat het een .txt-bestand is.
2
de eerste rij van de dataset bevat de namen van de variabelen
3
ontbrekende waarden zijn aangeduid als NA in de dataset
4
strings (\(\approx\) “woorden”) worden geïnterpreteerd als levels van een factorvariabele
4.2 Dataverkenning
We vatten alle variabelen samen voor een eerste kennismaking.
summary(fb)
Leerling School Klas PPVT Spreken
Min. : 2.0 S12 : 51 9A : 29 Min. : 31.0 Min. : 0.000
1st Qu.:219.8 S34 : 49 12A : 27 1st Qu.: 69.0 1st Qu.: 2.000
Median :445.5 S33 : 37 11A : 24 Median : 78.0 Median : 5.000
Mean :441.1 S38 : 36 12B : 24 Mean : 78.6 Mean : 6.786
3rd Qu.:660.2 S51 : 36 42A : 24 3rd Qu.: 88.0 3rd Qu.:10.000
Max. :867.0 S8 : 35 21A : 21 Max. :116.0 Max. :20.000
(Other):536 (Other):631 NA's :1 NA's :13
Luisteren SchrijvenLezen Attitude Thuistaal Geslacht
Min. : 0.00 Min. : 0.00 negatief: 27 Meertalig :207 man :402
1st Qu.:10.00 1st Qu.:13.00 positief:733 Nederlands:567 vrouw:378
Median :15.00 Median :18.00 NA's : 20 NA's : 6
Mean :14.95 Mean :21.16
3rd Qu.:20.00 3rd Qu.:29.00
Max. :25.00 Max. :50.00
NA's :2 NA's :1
We zien enkele NA-waarden. Die waarden laten we voorlopig in de dataset. Bij de variabelen Spreken en SchrijvenLezen zijn er minimale waarden van \(0\). Dit is eigenaardig want je zou op zijn minst verwachten dat er toch iets correct was op de testen. Laten we die nulwaarden voorlopig ook behouden in onze data.
De functies die we tot nu toe gebruikt hebben in dit hoofdstuk behoren allemaal tot base-R. In de volgende paragrafen exploreren we onze dataset met dplyr-functies.
4.3 Data samenvatten met dplyr
Een van kernideeën achter de tidyverse-aanpak is om geneste functies te vermijden en om met sequentiële code te werken. Ook het dollarteken als verwijzing naar een variabele in een dataset (data$variabele) wordt vermeden. Daarnaast beoogt tidyverse meer consistentie in de codesyntax.
Als eerste kennismaking met deze filosofie vergelijken we de berekening van het gemiddelde van PPVT in base-R en in tidyverse.
Kies de fb-dataset. Opgepast: kiezen veronderstelt dat je de data al geopend hebt. Als je meerdere datasets geopend hebt kun je er een kiezen.
2
we gebruiken summarize() om data samen te vatten, en meer specifiek de mean() functie. MEAN is een nieuwe naam voor het resultaat.
MEAN
1 78.5982
Het fbobject is een dataframe met 1 kolom en 1 rij, waarbij we zelf een naam gegeven hebben aan de variabele (MEAN). Op het eerste gezicht is de dplyr-code langer en omslachtiger. Het voordeel is echter dat we dezelfde code gemakkelijk kunnen uitbreiden met extra samenvattingen, en dat we de output in een dataframe krijgen.
een lijst met functies om de data samen te vatten.
mean median min max SD
1 78.5982 78 31 116 13.85053
Summarize() is een van de basisfunctie in dplyr. Daarnaast zijn er nog een viertal functies die samen gebruikt worden en die we hieronder achtereenvolgens toelichten.
select() selecteert variabelen/kolommen
filter() selecteert rijen
mutate() transformeert variabelen naar nieuwe variabelen
group_by() groepeert data volgens een (categorische) variabele
`summarise()` has grouped output by 'Geslacht'. You can override using the
`.groups` argument.
# A tibble: 4 × 7
# Groups: Geslacht [2]
Geslacht Attitude mean median min max SD
<fct> <fct> <dbl> <dbl> <int> <int> <dbl>
1 man negatief 67.7 67 36 99 14.6
2 man positief 82.0 82 31 116 14.8
3 vrouw negatief 67.5 64 49 81 9.78
4 vrouw positief 75.7 75 45 108 11.3
We zien onmiddellijk dat een positieve attitude tegenover Engels geassocieerd is met een hogere gemiddelde PPVT-score voor beide geslachten en dat dit iets meer uitgesproken is bij jongens.1
4.3.2 filter() en select()
We selecteren Leerlingen, Scholen en Klassen voor Leerlingen die meer dan \(110/120\) scoren voor PPVT:
Er zijn zeven scholen en in een daarvan zijn er twee leerlingen die meer dan \(110\) scoren voor PPVT.
4.3.3 mutate()
Met mutate() creëren we een nieuwe variabele die we toevoegen aan de dataset. We kunnen bijvoorbeeld een gestandaardiseerde PPVT score (z-score) berekenen en toevoegen. Waarbij we hieronder onmiddellijk ook de gemiddelde z-score berekenen per Geslacht.
# A tibble: 2 × 2
Geslacht AVG
<fct> <dbl>
1 man 0.220
2 vrouw -0.230
Jongens scoren boven het gemiddelde, meisjes eronder.
4.4 Data pivoteren
Vergelijk de twee datasets in Table 4.2. In Table 4.2 (a) krijgt elke observatie (elke score voor elk moment) een eigen rij. Daardoor zijn er twee rijen per leerling. We hebben een binaire categorische variabele Test en een continue variabele Score. In Table 4.2 (b) geeft elke rij de gegevens voor 1 leerling weer. Er zijn twee testmomenten (Pre- en Posttest) die apart worden weergegeven. Dit wijde dataformaat is gebruikelijk bij gepaarde en longitudinale data waarbij er meerdere metingen zijn voor 1 element. Het formaat is belangrijk om de data correct te kunnen analyseren en vooral te visualiseren. Daarom is het noodzakelijk om van het ene naar het andere formaat te kunnen omschakelen. Alles opnieuw overschrijven is een mogelijkheid, maar die is veel te omslachtig. We kunnen code gebruiken om de data te “pivoteren”.
Table 4.2: Het lange en wijde dataformaat
(a) Het lange dataformaat
Leerling
Test
Score
1
pretest
8
1
posttest
12
2
pretest
12
2
posttest
14
3
pretest
9
3
posttest
8
…
…
…
(b) Het wijde dataformaat
Leerling
Pretest
Posttest
1
8
12
2
12
14
3
9
8
…
…
…
We illustreren de twee pivotfuncties op basis van de data Table 4.2. We maken eerste een dataframe op basis van het wijde dataformaat.
In dit hoofdstuk hebben we kennis gemaakt met de voornaamste functie in de tidyverse-aanpak, voornamelijk dan met dplyr . Het grootste voordeel om met tidyverse te werken is de consistentie in de code en de relatieve eenvoud van de syntax. Dat alle output als een dataframe gestructureerd wordt, heeft als bijkomend voordeel dat die zich uitstekend leent voor een visualisatie met ggplot2.
Tot slot wil ik hier ook nog opmerken dat er ook kritiek gegeven kan worden op een al te exclusief gebruik van tidyverse. Norm Matloff geeft enkele sterke argumenten waarom ook base-R belangrijk blijft: https://github.com/matloff/TidyverseSkeptic. Zowel base-R als tidyverse gebruik ik in dit handboek en hebben hun plaats in onze gereedschapskist.
4.6 Terminologie
tibble
tidy data
data pivoteren
het lange en wijde dataformaat
Functies:
read.delim()
tibble()
tribble()
data.frame()
drop_na()
select()
filter()
mutate()
group_by()
summarise()
pivot_wider()
pivot_longer()
De Wilde, Vanessa, Marc Brysbaert, and June Eyckmans. 2019. “Learning English Through Out-of-School Exposure. Which Levels of Language Proficiency Are Attained and Which Types of Input Are Important?”Bilingualism: Language and Cognition 23 (1): 171–85. https://doi.org/10.1017/s1366728918001062.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the Tidyverse” 4: 1686. https://doi.org/10.21105/joss.01686.
Wickham, Hadley, Romain François, Lionel Henry, Kirill Müller, and Davis Vaughan. 2023. “Dplyr: A Grammar of Data Manipulation.”https://CRAN.R-project.org/package=dplyr.
We kunnen hier discussiëren over de kip of het ei. Heeft Attitude een positief effect of is de positieve attitude een gevolg van de betere score? We kunnen dit causaliteitsvraagstuk niet beantwoorden op basis van deze analyse. Vandaar ook de term “geassocieerd”, die beide richtingen toelaat.↩︎