6  Data combineren

In dit hoofdstuk bespreken we manieren om aan een bestaande dataset nieuwe rijen of kolommen toe te voegen en om twee bestaande datasets samen te voegen.

We gebruiken in dit hoofdstuk de volgende packages:

library(tidyverse)
library(rio)

En als voorbeelddata de Canadian Election Study van 2019:

canada <- import("2019 Canadian Election Study.rds")

6.1 Datasets combineren: rijen of kolommen toevoegen

6.1.1 Rijen toevoegen

Als we twee datasets hebben met dezelfde kolommen (variabelen), kunnen we de rijen van de twee datasets samenvoegen met bind_rows uit package dplyr (dit package wordt geladen met de tidyverse).

Als voorbeeld hebben we twee datasets met dezelfde variabelen, name en age:

dta1 <- data.frame(name = c("Billy", "Xin", "Hugo"), age = c(20, 30, 40))
dta2 <- data.frame(name = c("Theresa", "Elin", "Lena"), age = c(25, 35, 45))

dta1 
   name age
1 Billy  20
2   Xin  30
3  Hugo  40
dta2
     name age
1 Theresa  25
2    Elin  35
3    Lena  45

Wij kunnen deze datasets als volgt combineren:

dta_combined <- bind_rows(dta1, dta2)
dta_combined
     name age
1   Billy  20
2     Xin  30
3    Hugo  40
4 Theresa  25
5    Elin  35
6    Lena  45

6.1.2 Kolommen toevoegen

Als we extra kolommen willen toevoegen aan een dataframe, kunnen we bind_cols uit package dplyr gebruiken (dit package wordt geladen met de tidyverse).

Als we bijvoorbeeld twee datasets hebben, één met de naam en leeftijd van mensen, en een andere met hun zelfgerapporteerde geslacht:

dta <- data.frame(name = c("Billy", "Xin", "Hugo"), age = c(20, 30, 40))
gender <- data.frame(gender = c("Non-binary", "Female", "Male"))
dta
   name age
1 Billy  20
2   Xin  30
3  Hugo  40
gender
      gender
1 Non-binary
2     Female
3       Male

We kunnen dit combineren met bind_cols:

bind_cols(dta, gender)
   name age     gender
1 Billy  20 Non-binary
2   Xin  30     Female
3  Hugo  40       Male
Belangrijk

bind_cols zal matchen op positie, dus de volgorde van rijen moet precies hetzelfde zijn. Voor meer flexibele manieren om kolommen aan een dataset toe te voegen, zie “Datasets samenvoegen” hieronder.

6.2 Datasets samenvoegen (join)

Als we twee datasets hebben met een gemeenschappelijke variabele (d.w.z. een variabele met dezelfde naam en vergelijkbare codering, bijvoorbeeld een landnaam of een unieke identificatiecode), kunnen we de datasets combineren met join van dplyr.

Laten we beginnen met wat voorbeeldgegevens over 4 landen:

country_dta1 <- data.frame(country = c("USA", "Germany", "Netherlands", "Kenya"),
                           population = c(332, 84, 18, 56))

country_dta2 <- data.frame(country = c("Netherlands", "Germany", "Kenya", "Argentina"),
                          official_name = c("Nederland", "Bundesrepublik Deutschland", "Republic of Kenya", "República Argentina"))

country_dta1
      country population
1         USA        332
2     Germany         84
3 Netherlands         18
4       Kenya         56
country_dta2
      country              official_name
1 Netherlands                  Nederland
2     Germany Bundesrepublik Deutschland
3       Kenya          Republic of Kenya
4   Argentina        República Argentina

Merk op dat slechts drie landen voorkomen in beide datasets, maar de variabele country is aanwezig in beide dataframes en de waarden (d.w.z. de spelling van de namen van de landen) zijn hetzelfde voor de drie landen die in beide datasets voorkomen.

We kunnen de gegevens in deze datasets als volgt samenvoegen, met behulp van zogenaamde ‘joins’ van pacakge dplyr. De functie full_join geeft alle rijen in beide datasets terug:

joined_data <- full_join(x = country_dta1, 
                         y = country_dta2, 
                         by = c("country"))
x = country_dta1

Dit specificeert de eerste van de twee datasets. Vervang door je eigen dataset als je met je eigen gegevens werkt.

y = country_dta2

Dit specificeert de tweede van de twee datasets.

by = c("country")

Dit specificeert de kolom waarop we de waarden van de twee dataframes willen matchen (gespecificeerd als een character vector, d.w.z. tussen dubbele haakjes). In ons voorbeeld gebruiken we de variabele country, omdat deze variabele vergelijkbaar is tussen onze twee datasets.

joined_data
      country population              official_name
1         USA        332                       <NA>
2     Germany         84 Bundesrepublik Deutschland
3 Netherlands         18                  Nederland
4       Kenya         56          Republic of Kenya
5   Argentina         NA        República Argentina

We zien dat alle vijf landen aanwezig zijn in de samengevoegde dataset. De VS ontbreekt in country_dta2, dus er ontbreekt een waarde (NA) voor official_name in de gecombineerde dataset. Argentinië ontbreekt in country_dta1 en heeft dus een ontbrekende waarde voor population in de gecombineerde dataset.

Er zijn vier soorten joins:

Functie Gecombineerde dataset omvat…
inner_join() … alle rijen in x en y.
left_join() … alle rijen in x.
right_join() … alle rijen in y.
full_join() … alle rijen in x of y.

We kunnen het resultaat zien als we de vier soorten joins uitvoeren en printen:

# Inner join: alleen de drie landen die in beide datasets voorkomen
inner_join(x = country_dta1, y = country_dta2, by = c("country"))
      country population              official_name
1     Germany         84 Bundesrepublik Deutschland
2 Netherlands         18                  Nederland
3       Kenya         56          Republic of Kenya
# Left join: alleen de vier landen in de eerste dataset
left_join(x = country_dta1, y = country_dta2, by = c("country"))
      country population              official_name
1         USA        332                       <NA>
2     Germany         84 Bundesrepublik Deutschland
3 Netherlands         18                  Nederland
4       Kenya         56          Republic of Kenya
# Right join: alleen de vier landen in de tweede dataset
right_join(x = country_dta1, y = country_dta2, by = c("country"))
      country population              official_name
1     Germany         84 Bundesrepublik Deutschland
2 Netherlands         18                  Nederland
3       Kenya         56          Republic of Kenya
4   Argentina         NA        República Argentina
# Full join: alle vijf de landen
full_join(x = country_dta1, y = country_dta2, by = c("country"))
      country population              official_name
1         USA        332                       <NA>
2     Germany         84 Bundesrepublik Deutschland
3 Netherlands         18                  Nederland
4       Kenya         56          Republic of Kenya
5   Argentina         NA        República Argentina

6.2.1 Joining met verschillende variabelen

Als we twee dataframes hebben met verschillende namen, moeten we R instrueren welke variabelen moeten worden vergeleken.

Stel bijvoorbeeld dat we een derde dataframe hebben met landeninformatie:

country_dta3 <- data.frame(country_name = c("USA", "Netherlands", "Germany"),
                           capital_city = c("Washington DC", "Amsterdam", "Berlin"))
country_dta3
  country_name  capital_city
1          USA Washington DC
2  Netherlands     Amsterdam
3      Germany        Berlin

We merken op dat de variabele met de naam van het land in dit dataframe country_name heet. Om deze te combineren met country_dta1, moeten we by als volgt specificeren:

full_join(x = country_dta1, y = country_dta3, 
          by = c("country" = "country_name"))
      country population  capital_city
1         USA        332 Washington DC
2     Germany         84        Berlin
3 Netherlands         18     Amsterdam
4       Kenya         56          <NA>
by = c("country" = "country_name")

De syntaxis "country" = "country_name" betekent dat we variabele country uit de eerste dataset vergelijken met variabele country_name uit de tweede dataset.

Merk op dat deze oplossing alleen werkt als de landennamen identiek gespeld zijn (en alleen de naam van de variabele verschilt). Het onderstaande zal niet goed werken, omdat de landennamen niet vergelijkbaar zijn tussen de twee datasets:

country_dta4 <- data.frame(country = c("United States of America", "Deutschland", "Nederland"),
                           capital_city = c("Washington DC", "Berlin", "Amsterdam"))

country_dta4
                   country  capital_city
1 United States of America Washington DC
2              Deutschland        Berlin
3                Nederland     Amsterdam
full_join(country_dta1, country_dta4)
                   country population  capital_city
1                      USA        332          <NA>
2                  Germany         84          <NA>
3              Netherlands         18          <NA>
4                    Kenya         56          <NA>
5 United States of America         NA Washington DC
6              Deutschland         NA        Berlin
7                Nederland         NA     Amsterdam

In dergelijke gevallen is de oplossing om eerst de variabele die wordt gebruikt voor de matching te hercoderen:

country_dta4_recoded <- country_dta4 |>
  mutate(country = recode(country, 
                          "United States of America" = "USA",
                          "Deutschland" = "Germany",
                          "Nederland" = "Netherlands"))

De landennamen uit beide datasets komen nu overeen, en we kunnen ze dus samenvoegen:

full_join(country_dta1, country_dta4_recoded)
      country population  capital_city
1         USA        332 Washington DC
2     Germany         84        Berlin
3 Netherlands         18     Amsterdam
4       Kenya         56          <NA>