clean data r datasets opschonen tutorial uitleg

In dit blogartikel gaan we in op hoe je datasets kunt opschonen in R. We gebruiken een dataset met KNMI meetgegevens die je hier kunt downloaden zodat je - als je dat leuk vindt - mee kunt doen.

Dit blog is een onderdeel van een blogserie over R waarin we o.a. ingaan op hoe je R installeert, hoe je in RStudio werkt, data manipuleert met bijvoorbeeld dplyr of data.table, of data visualiseert met ggplot2 in bijvoorbeeld een histogram of boxplot.

We gaan in dit blog in op:


1. Missende waarden

Het komt vaak voor dat een dataset missende waarden bevat.

Je kunt hier bijvoorbeeld als volgt mee omgaan:

  • Rijen met missende waarden verwijderen
  • Missende waarden vervangen door een andere waarde

In onderstaande cel openen we de KNMI dataset:

library(readxl)

df_knmi <- read_excel("data/knmi_measurements.xlsx", guess_max = 10000)

df_knmi
## # A tibble: 273,954 × 4
##    station_id     date temperature rainfall
##         <dbl>    <dbl>       <dbl>    <dbl>
##  1        260 19010101         -49       NA
##  2        260 19010102         -18       NA
##  3        260 19010103         -26       NA
##  4        260 19010104         -65       NA
##  5        260 19010105         -60       NA
##  6        260 19010106        -100       NA
##  7        260 19010107         -92       NA
##  8        260 19010108         -49       NA
##  9        260 19010109          11       NA
## 10        260 19010110          15       NA
## # ℹ 273,944 more rows
df_knmi$station_id[df_knmi$station_id == 260] <- "peer"

df_knmi
## # A tibble: 273,954 × 4
##    station_id     date temperature rainfall
##    <chr>         <dbl>       <dbl>    <dbl>
##  1 peer       19010101         -49       NA
##  2 peer       19010102         -18       NA
##  3 peer       19010103         -26       NA
##  4 peer       19010104         -65       NA
##  5 peer       19010105         -60       NA
##  6 peer       19010106        -100       NA
##  7 peer       19010107         -92       NA
##  8 peer       19010108         -49       NA
##  9 peer       19010109          11       NA
## 10 peer       19010110          15       NA
## # ℹ 273,944 more rows
  • Met de summary() functie krijgen we een statistische samenvatting:
summary(df_knmi)
##   station_id             date           temperature         rainfall      
##  Length:273954      Min.   :19010101   Min.   :-166.00   Min.   :  -1.00  
##  Class :character   1st Qu.:19600108   1st Qu.:  54.00   1st Qu.:   0.00  
##  Mode  :character   Median :19901002   Median : 100.00   Median :   1.00  
##                     Mean   :19805469   Mean   :  99.35   Mean   :  21.38  
##                     3rd Qu.:20061015   3rd Qu.: 149.00   3rd Qu.:  24.00  
##                     Max.   :20220531   Max.   : 309.00   Max.   :1423.00  
##                                                          NA's   :72715
  • Hierin zien we dat kolom rainfall missende waarden (NA's) bevat.

Met vertrouwen waardevolle inzichten halen uit data met R? Bekijk dan onze opleiding R voor data analyse.

Voorkomendheid van missende waarden

Met de any() en is.na() functies kun je gemakkelijk zien of een kolom missende waarden bevat:

any(is.na(df_knmi$rainfall))
## [1] TRUE

Rijen met missende waarden verwijderen

  • In de originele dataset bevinden zich het volgende aantal rijen en kolommen:
dim(df_knmi)
## [1] 273954      4
  • Met de functie na.omit() (omit = weglaten) verwijderen we alle rijen waarin een lege waarde voorkomt:
df_knmi_cleaned <- na.omit(df_knmi)

df_knmi_cleaned
## # A tibble: 201,239 × 4
##    station_id     date temperature rainfall
##    <chr>         <dbl>       <dbl>    <dbl>
##  1 peer       19060101         -32        0
##  2 peer       19060102         -23        0
##  3 peer       19060103           7        0
##  4 peer       19060104          65       36
##  5 peer       19060105          71      134
##  6 peer       19060106          73      136
##  7 peer       19060107          53       32
##  8 peer       19060108          29      104
##  9 peer       19060109          46       29
## 10 peer       19060110          58        1
## # ℹ 201,229 more rows
  • We zien dat het aantal rijen is afgenomen.
  • We testen nogmaals op missende waarden:
any(is.na(df_knmi_cleaned))
## [1] FALSE
  • Er zijn geen missende waarden meer.

Missende waarden vervangen

We gaan missende waarden in kolom temperature vervangen door de gemiddelde temperatuur van alle overige metingen.

In onderstaande cel doen we het volgende:

  • Berekenen de gemiddelde temperatuur in cellen met metingen:
mean_temperature <- mean(df_knmi_cleaned$temperature, na.rm = TRUE)

mean_temperature
## [1] 100.6928

In onderstaande cel doen we het volgende:

  • Maken df_knmi_cleaned aan, een kopie van df_knmi
  • We maken een selectie van de waarden in kolom temperatuur die missend zijn met functie is.na()
  • Vullen deze waarden met mean_temperature
  • Bekijken of er nu nog missende waarden in de kolom voorkomen
df_knmi_cleaned <- df_knmi

df_knmi_cleaned$temperature[
  is.na(df_knmi_cleaned$temperature)
] <- mean_temperature

any(is.na(df_knmi_cleaned$temperature))
## [1] FALSE
  • Er zijn geen missende waarden meer in de kolom

2. Aanpassen van een kolomnaam

Met de colnames() functie kunnen we de namen van kolommen ophalen:

colnames(df_knmi_cleaned)
## [1] "station_id"  "date"        "temperature" "rainfall"

In onderstaande cel doen we het volgende:

  • Maken een kopie
  • Gebruiken de colnames() functie om een kolom te hernoemen
  • Ophalen van namen
  • Selectie op naam "date"
  • Aanpassen naar "measurement_date"
  • Bekijken het resultaat

df_knmi_rename <- df_knmi

colnames(df_knmi_rename)[colnames(df_knmi_rename) == "date"] <- "measurement_date"

df_knmi_rename
## # A tibble: 273,954 × 4
##    station_id measurement_date temperature rainfall
##    <chr>                 <dbl>       <dbl>    <dbl>
##  1 peer               19010101         -49       NA
##  2 peer               19010102         -18       NA
##  3 peer               19010103         -26       NA
##  4 peer               19010104         -65       NA
##  5 peer               19010105         -60       NA
##  6 peer               19010106        -100       NA
##  7 peer               19010107         -92       NA
##  8 peer               19010108         -49       NA
##  9 peer               19010109          11       NA
## 10 peer               19010110          15       NA
## # ℹ 273,944 more rows
  • De naam is aangepast

3. Kolommen aanpassen

Het volgende komt regelmatig voor:

  • Waarden in een bestaande kolom aanpassen
  • Datatype in een kolom wilt aanpassen
  • Een nieuwe kolom toevoegen

Bestaande kolom aanpassen

In de KNMI documentatie lezen we het volgende over kolom temperature:

Maximum temperatuur (in 0.1 graden Celsius)

Maximum temperature (in 0.1 degrees Celsius)

Om de temperaturen makkelijk te gebruiken moeten we deze dus delen door 10.

Dit doen we in onderstaande cel:


df_knmi$temperature <- df_knmi$temperature / 10

df_knmi
## # A tibble: 273,954 × 4
##    station_id     date temperature rainfall
##    <chr>         <dbl>       <dbl>    <dbl>
##  1 peer       19010101        -4.9       NA
##  2 peer       19010102        -1.8       NA
##  3 peer       19010103        -2.6       NA
##  4 peer       19010104        -6.5       NA
##  5 peer       19010105        -6         NA
##  6 peer       19010106       -10         NA
##  7 peer       19010107        -9.2       NA
##  8 peer       19010108        -4.9       NA
##  9 peer       19010109         1.1       NA
## 10 peer       19010110         1.5       NA
## # ℹ 273,944 more rows
  • Je benoemt de te veranderen kolom, en benoemt de aanpassing

Datatype in een kolom aanpassen

We gaan het datatype van kolom date instellen als datum.

  • Bij het uitlezen van een dataset bepaalt R zelf de datatypes van de kolommen.
  • Dit gaat niet altijd goed.
library(readxl)

df_knmi <- read_excel("data/knmi_measurements.xlsx", guess_max = 10000)

str(df_knmi)
## tibble [273,954 × 4] (S3: tbl_df/tbl/data.frame)
##  $ station_id : num [1:273954] 260 260 260 260 260 260 260 260 260 260 ...
##  $ date       : num [1:273954] 1.9e+07 1.9e+07 1.9e+07 1.9e+07 1.9e+07 ...
##  $ temperature: num [1:273954] -49 -18 -26 -65 -60 -100 -92 -49 11 15 ...
##  $ rainfall   : num [1:273954] NA NA NA NA NA NA NA NA NA NA ...
  • De kolom date wordt gezien als getal, niet als datum.

In onderstaande cel doen we het volgende:

  • We gebruiken de as.Date() functie om een kolom om te zetten naar datatype date.
  • Daarvoor moet de kolom eerst datatype tekst hebben.
  • Hiervoor zetten we de kolom eerst om naar tekst met functie as.character().
  • Met argument format specificeren we het huidige formaat van de datumnotatie.
  • Dat is hier 19991220 -> YYYYmmdd -> "%Y%m%d"
  • Kijk voor alle opties in de documentatie.
df_knmi$date <- as.Date(as.character(df_knmi$date), format = "%Y%m%d")

str(df_knmi)
## tibble [273,954 × 4] (S3: tbl_df/tbl/data.frame)
##  $ station_id : num [1:273954] 260 260 260 260 260 260 260 260 260 260 ...
##  $ date       : Date[1:273954], format: "1901-01-01" "1901-01-02" ...
##  $ temperature: num [1:273954] -49 -18 -26 -65 -60 -100 -92 -49 11 15 ...
##  $ rainfall   : num [1:273954] NA NA NA NA NA NA NA NA NA NA ...
  • Het datatype van kolom date is nu Date.

Een nieuwe kolom toevoegen

In een R dataframe kun je gemakkelijk een nieuwe kolom toevoegen.

Je doet dit door de naam van de nieuwe kolom te benoemen, en de waarden te specificeren.

We gaan gebaseerd op de kolom date, een kolom met de maand van de datum toevoegen.

In onderstaande cel doen we het volgende:

  • Importeren package lubridate: handige functies voor datums en tijd.
  • Met functie month() vanuit lubridate verkrijgen we de maand van de datum.
  • De maand bewaren we in een nieuwe kolom die we "month" noemen.
library(lubridate)

df_knmi$month <- month(df_knmi$date)

df_knmi
## # A tibble: 273,954 × 5
##    station_id date       temperature rainfall month
##         <dbl> <date>           <dbl>    <dbl> <dbl>
##  1        260 1901-01-01         -49       NA     1
##  2        260 1901-01-02         -18       NA     1
##  3        260 1901-01-03         -26       NA     1
##  4        260 1901-01-04         -65       NA     1
##  5        260 1901-01-05         -60       NA     1
##  6        260 1901-01-06        -100       NA     1
##  7        260 1901-01-07         -92       NA     1
##  8        260 1901-01-08         -49       NA     1
##  9        260 1901-01-09          11       NA     1
## 10        260 1901-01-10          15       NA     1
## # ℹ 273,944 more rows
  • De kolom "month" is toegevoegd.
  • Hetzelfde kunnen we bijvoorbeeld doen voor jaar met functie year() :
df_knmi$year <- year(df_knmi$date)

df_knmi
## # A tibble: 273,954 × 6
##    station_id date       temperature rainfall month  year
##         <dbl> <date>           <dbl>    <dbl> <dbl> <dbl>
##  1        260 1901-01-01         -49       NA     1  1901
##  2        260 1901-01-02         -18       NA     1  1901
##  3        260 1901-01-03         -26       NA     1  1901
##  4        260 1901-01-04         -65       NA     1  1901
##  5        260 1901-01-05         -60       NA     1  1901
##  6        260 1901-01-06        -100       NA     1  1901
##  7        260 1901-01-07         -92       NA     1  1901
##  8        260 1901-01-08         -49       NA     1  1901
##  9        260 1901-01-09          11       NA     1  1901
## 10        260 1901-01-10          15       NA     1  1901
## # ℹ 273,944 more rows
summary(df_knmi$year)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1901    1960    1990    1980    2006    2022
  • De kolom "year" is toegevoegd.

Expert worden in R?

Wil jij goed leren werken in R? Tijdens onze Opleiding R leer je alles wat je nodig hebt om zelfstandig analyses uit te voeren in R.

by: