r-matrix-uitleg-tutorial

Als je met R werkt, kom je al snel de term matrix tegen. Wat is het en wanneer gebruik je dit nu echt? En waarom zou je een matrix gebruiken in plaats van een data.frame?

Veel tutorials laten zien hoe je een matrix maakt, maar niet waarom je die überhaupt zou gebruiken. In deze blog pakken we het praktisch aan. We leggen niet alleen uit wat een matrix in R is, maar vooral hoe het werkt in relatie tot andere datastructuren, wanneer het handig is, waar het vaak misgaat, en hoe het terugkomt in echte data- en AI-projecten.

Wat is een matrix in R?

Een matrix in R is een tweedimensionale datastructuur met rijen en kolommen. Dat lijkt op een tabel, maar er is een belangrijk verschil met een data.frame: in een matrix moeten alle waarden hetzelfde datatype hebben. Je kunt dus prima een matrix met alleen getallen hebben, of alleen tekst, maar niet netjes een combinatie van tekst en numerieke waarden zoals je vaak in een dataset ziet.

Dat maakt een matrix minder flexibel dan een data.frame, maar juist geschikt voor berekeningen. Onder de motorkap is een matrix in R in feite een vector met extra informatie over het aantal rijen en kolommen. Daardoor is een matrix vaak compact en efficiënt, vooral wanneer je werkt met numerieke data.

Je kunt het verschil grofweg zo onthouden: een data.frame is gemaakt om data te organiseren en te verkennen, terwijl een matrix vooral bedoeld is om mee te rekenen.

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

Voorbeelddata: gesimuleerde KNMI-data

We beginnen met een klein, herkenbaar voorbeeld. Stel dat we voor zeven dagen temperatuur, neerslag en zonuren hebben. Dat is precies het soort compacte dataset waarmee je goed kunt laten zien hoe de stap van data.frame naar matrix werkt.

Hieronder maken we een klein voorbeeld van gesimuleerde weerdata voor zeven dagen. Je kunt natuurlijk ook een lokale dataset uitlezen met R.

set.seed(42)

days <- paste0("day_", 1:7)

temperature <- round(rnorm(7, mean = 17, sd = 4), 1)
precipitation <- round(runif(7, min = 0, max = 18), 1)
sun_hours <- round(runif(7, min = 0, max = 12), 1)

weather_df <- data.frame(
  day = days,
  temperature = temperature,
  precipitation = precipitation,
  sun_hours = sun_hours
)

weather_df
daytemperatureprecipitationsun_hours
day_122.58.31.7
day_214.716.911.9
day_318.517.611.4
day_419.52.11.0
day_518.68.56.2
day_616.610.14.7
day_723.016.310.9

Het resultaat is een data.frame met één tekstkolom en drie numerieke kolommen.

Dit lijkt sterk op hoe data er in de praktijk vaak uitziet. Je hebt meestal een tabel met observaties per rij, variabelen per kolom, en niet alle kolommen hebben hetzelfde datatype. Juist daarom is een data.frame in R vaak je natuurlijke startpunt.

Een data.frame omzetten naar matrix

Zodra je alleen met de numerieke waarden wilt rekenen, wordt een matrix interessant. Je selecteert dan de kolommen die numeriek zijn en zet die om naar een matrix.

Hieronder zetten we het volledige data.frame om naar een matrix.

as.matrix(weather_df)
     day     temperature precipitation sun_hours
[1,] "day_1" "22.5"      " 8.3"        " 1.7"   
[2,] "day_2" "14.7"      "16.9"        "11.9"   
[3,] "day_3" "18.5"      "17.6"        "11.4"   
[4,] "day_4" "19.5"      " 2.1"        " 1.0"   
[5,] "day_5" "18.6"      " 8.5"        " 6.2"   
[6,] "day_6" "16.6"      "10.1"        " 4.7"   
[7,] "day_7" "23.0"      "16.3"        "10.9"  

Omdat er een tekstkolom (day) in zit, zet R alle waarden om naar tekst. Dat betekent dat je numerieke data ineens niet meer numeriek is.

Daarom moeten we, als we verder willen werken met numerieke data, de juiste kolommen selecteren.

Hieronder zetten we alleen de numerieke kolommen om naar een matrix en geven we de rijen leesbare namen.

weather_matrix <- as.matrix(weather_df[, c("temperature", "precipitation", "sun_hours")])
rownames(weather_matrix) <- weather_df$day

weather_matrix
      temperature precipitation sun_hours
day_1        22.5           8.3       1.7
day_2        14.7          16.9      11.9
day_3        18.5          17.6      11.4
day_4        19.5           2.1       1.0
day_5        18.6           8.5       6.2
day_6        16.6          10.1       4.7
day_7        23.0          16.3      10.9

Het resultaat is een matrix van 7 rijen en 3 kolommen met alleen numerieke waarden.

In de praktijk zie je vaak dit patroon:

  • Je begint met een data.frame (data begrijpen)
  • Je selecteert features (data voorbereiden)
  • Je zet het waar nodig om naar een matrix (rekenen / modelleren)

Van data.frame naar matrix en andere datastructuren: wat gebruik je wanneer?

Tot nu toe hebben we vooral gekeken naar data.frames en matrices. Maar om echt goed te begrijpen wanneer je een matrix gebruikt, helpt het om iets uit te zoomen. R heeft namelijk meerdere datastructuren die elk hun eigen rol hebben. In de praktijk gebruik je die vaak samen, niet los van elkaar.

De vector: de basis van alles

In R begint veel bij een vector. Een vector is simpelweg een reeks waarden van hetzelfde type. Als je één kolom uit een data.frame haalt, krijg je in veel gevallen een vector terug.

Als je de temperatuurkolom apart ophaalt, krijg je een vector terug.

temperature
[1] 22.5 14.7 18.5 19.5 18.6 16.6 23.0

Het resultaat is een reeks numerieke waarden in één dimensie.

Dat lijkt misschien simpel, maar het is fundamenteel. Een matrix is namelijk in de basis niets meer dan een vector met dimensies. Dit inzicht helpt enorm om R beter te begrijpen, omdat veel datastructuren in R uiteindelijk op eenvoudige bouwstenen terug te voeren zijn.

De matrix: voor gestructureerde numerieke berekeningen

Zodra je gegevens hebt in twee dimensies, bijvoorbeeld dagen bij rijen en variabelen bij kolommen, kom je uit bij een matrix.

Hier zie je de matrix terug die we net hebben gemaakt.

weather_matrix
temperatureprecipitationsun_hours
day_122.58.31.7
day_214.716.911.9
day_318.517.611.4
day_419.52.11.0
day_518.68.56.2
day_616.610.14.7
day_723.016.310.9

Het resultaat is een tweedimensionale numerieke structuur met rijen en kolommen.

Een matrix is handig wanneer alle waarden hetzelfde type hebben en je de data wilt gebruiken voor berekeningen. Denk aan gemiddelde waarden, matrixvermenigvuldiging of modelinput. Op dat soort momenten is een matrix vaak logischer dan een data.frame.

Het data.frame: voor echte datasets

Voor de meeste dagelijkse analyses werk je niet direct met matrices, maar met data.frames. Dat komt omdat echte datasets zelden netjes homogeen zijn. Je hebt vaak tekstkolommen, datums, categorieën en numerieke variabelen naast elkaar.

Met str() kun je de structuur van het data.frame bekijken.

str(weather_df)
'data.frame': 7 obs. of  4 variables:
 $ day          : chr  "day_1" "day_2" "day_3" "day_4" ...
 $ temperature  : num  22.5 14.7 18.5 19.5 18.6 16.6 23
 $ precipitation: num  8.3 16.9 17.6 2.1 8.5 10.1 16.3
 $ sun_hours    : num  1.7 11.9 11.4 1 6.2 4.7 10.9

Het resultaat laat zien dat het data.frame kolommen bevat met verschillende datatypes.

Dat is precies de kracht van een data.frame. Je kunt verschillende soorten informatie in één object bewaren en daar prettig mee werken. Voor verkennen, filteren, combineren en opschonen is een data.frame meestal de beste keuze.

De list: voor flexibiliteit

Soms wil je verschillende objecten samen opslaan, ook als ze niet dezelfde vorm hebben. Dan gebruik je een list. Een list kan bijvoorbeeld tegelijk een vector en een matrix bevatten.

Deze code maakt een list met meerdere soorten objecten.

example_list <- list(
  temperatures = temperature,
  summary = mean(temperature),
  matrix = weather_matrix
)

example_list
$temperatures
[1] 22.5 14.7 18.5 19.5 18.6 16.6 23.0

$summary
[1] 19.05714

$matrix
      temperature precipitation sun_hours
day_1        22.5           8.3       1.7
day_2        14.7          16.9      11.9
day_3        18.5          17.6      11.4
day_4        19.5           2.1       1.0
day_5        18.6           8.5       6.2
day_6        16.6          10.1       4.7
day_7        23.0          16.3      10.9

Het resultaat is een flexibel object dat verschillende typen inhoud naast elkaar bewaart.

In de praktijk zijn list-objecten vooral handig wanneer je meerdere tussenstappen of resultaten wilt bundelen, bijvoorbeeld in functies of complexere workflows.

Hoe dit samenkomt in de praktijk

In echte projecten lopen deze datastructuren vaak in elkaar over. Je begint met een data.frame, haalt daar een vector uit, zet een deel om naar een matrix, en stopt meerdere objecten eventueel samen in een list.

df <- weather_df
vec <- df$temperature
mat <- as.matrix(df[, 2:4])
lst <- list(df = df, mat = mat)

Het resultaat is dat dezelfde informatie in verschillende vormen beschikbaar is, elk voor een ander doel.

Dat is een belangrijk inzicht. De vraag is meestal niet welke datastructuur "de beste" is, maar welke datastructuur op dat moment het beste past bij wat je wilt doen. Voor begrip en bewerking is een data.frame vaak ideaal. Voor rekenen is een matrix vaak logischer. En vectors en lists spelen daar ondersteunende rollen in.

Zelf een matrix maken met matrix()

Je hoeft niet altijd te starten vanuit een data.frame. Je kunt een matrix ook direct maken met de functie matrix(). Dat is interessant om te zien, omdat je dan meteen iets belangrijks leert over hoe R met matrices omgaat.

Deze code maakt een matrix op basis van een vector met waarden.

values <- c(temperature, precipitation, sun_hours)

matrix_colwise <- matrix(values, ncol = 3)
matrix_colwise
     [,1] [,2] [,3]
[1,] 22.5  8.3  1.7
[2,] 14.7 16.9 11.9
[3,] 18.5 17.6 11.4
[4,] 19.5  2.1  1.0
[5,] 18.6  8.5  6.2
[6,] 16.6 10.1  4.7
[7,] 23.0 16.3 10.9

Het resultaat is een matrix die standaard kolomsgewijs is gevuld.

Let op: in values staan eerst alle temperatuurwaarden, daarna alle neerslagwaarden en daarna alle zonuren. In combinatie met kolomsgewijs vullen bepaalt dat hoe de uiteindelijke matrix eruitziet.

Met byrow = TRUE vul je de waarden rij voor rij in plaats van kolom voor kolom, waardoor de structuur van de matrix verandert.

matrix_rowwise <- matrix(values, ncol = 3, byrow = TRUE)
matrix_rowwise
     [,1] [,2] [,3]
[1,] 22.5 14.7 18.5
[2,] 19.5 18.6 16.6
[3,] 23.0  8.3 16.9
[4,] 17.6  2.1  8.5
[5,] 10.1 16.3  1.7
[6,] 11.9 11.4  1.0
[7,]  6.2  4.7 10.9

Vergelijk deze output met de vorige: de vulrichting bepaalt direct hoe de structuur van de matrix eruitziet.

Werken met een matrix: selecteren en bewerken

Waarden selecteren

Als je eenmaal een matrix hebt, is de basisstructuur gelukkig heel overzichtelijk. Je selecteert altijd eerst de rij en dan de kolom. Dat maakt het gedrag van matrices voorspelbaar.

Deze code laat zien hoe je een hele rij, een hele kolom en één specifieke waarde uit een matrix selecteert.

weather_matrix[1, ]      # first day
weather_matrix[, 1]      # all temperatures
weather_matrix[3, 2]     # specific value
  temperature precipitation     sun_hours 
         22.5           8.3           1.7 

day_1 day_2 day_3 day_4 day_5 day_6 day_7 
 22.5  14.7  18.5  19.5  18.6  16.6  23.0 

[1] 17.6

Het resultaat laat drie vormen van selectie zien: een rij, een kolom en één losse celwaarde.

Omdat matrices homogeen zijn, zijn dit soort selecties meestal eenvoudig te begrijpen. Er zit geen extra complexiteit in van verschillende datatypes per kolom, zoals je die bij data.frames soms wel hebt.

Waarden aanpassen

Je kunt ook waarden in een matrix aanpassen.

Deze code verandert de temperatuur op de eerste dag.

weather_matrix[1, 1] <- 25.0
weather_matrix
      temperature precipitation sun_hours
day_1        25.0           8.3       1.7
day_2        14.7          16.9      11.9
day_3        18.5          17.6      11.4
day_4        19.5           2.1       1.0
day_5        18.6           8.5       6.2
day_6        16.6          10.1       4.7
day_7        23.0          16.3      10.9

Het resultaat is dat één specifieke cel in de matrix is overschreven met een nieuwe waarde.

Dat lijkt simpel, maar laat goed zien dat een matrix niet alleen een passieve opslagvorm is. Je kunt er ook actief mee werken, bijvoorbeeld in simulaties of iteratieve berekeningen.

Waarom matrices handig zijn: snelle berekeningen

De echte meerwaarde van een matrix zie je zodra je berekeningen gaat uitvoeren. Omdat alle waarden van hetzelfde type zijn, kan R daar efficiënt mee omgaan.

Deze code berekent gemiddelden per kolom en totalen per rij.

colMeans(weather_matrix)
rowSums(weather_matrix)
  temperature precipitation     sun_hours 
    19.414286     11.400000      6.828571 

day_1 day_2 day_3 day_4 day_5 day_6 day_7 
 35.0  43.5  47.5  22.6  33.3  31.4  50.2 

Het resultaat is een compacte samenvatting van de matrix per kolom en per rij.

Dit soort operaties vormt de basis van veel statistische analyses. Het laat ook goed zien waarom matrices zo belangrijk zijn in data science. Niet omdat je ze altijd direct ziet, maar omdat ze onder de motorkap heel geschikt zijn voor snelle numerieke bewerkingen.

Waar gebruik je matrices echt voor?

Als je alleen tutorials leest, zou je kunnen denken dat je in R voortdurend expliciet met matrices werkt. In de praktijk ligt dat genuanceerder. Meestal werk je vooral met data.frames, en verschijnen matrices als tussenstap zodra je data wilt omzetten naar iets waarop een model of berekening kan draaien.

In veel machine learning workflows zie je dit letterlijk terug: ruwe data start als data.frame, maar vóór modellering wordt de input vaak omgezet naar een numerieke matrix.

Zo ziet zo'n eenvoudige tussenstap eruit.

df <- weather_df
X <- as.matrix(df[, c("temperature", "precipitation")])

Het resultaat is dat je vanuit een data.frame een numerieke matrix maakt die geschikt is voor verdere berekeningen.

Dat is precies hoe het in veel projecten gaat: het data.frame is prettig om mee te werken, terwijl de matrix beter past zodra je gaat rekenen of modelleren. Bij regressieanalyse, clustering, dimensiereductie en veel andere methoden speelt die matrixvorm een centrale rol, ook als je die zelf niet steeds direct ziet. Bijvoorbeeld: bij een regressiemodel wordt je input intern omgezet naar een matrix, waarbij elke kolom een feature is en elke rij een observatie.

De belangrijkste nuance is dan ook niet dat je in de praktijk vooral matrices gebruikt. De nuance is dat je vaak met data.frames werkt, terwijl matrices onmisbaar zijn in de stap daarna.

Conclusie

Matrices zijn in R zelden je startpunt, maar vaak wel een belangrijke tussenstap. Werk je met gemengde data, dan is een data.frame meestal de logische keuze. Wil je rekenen of modelleren met numerieke data, dan kom je al snel uit bij een matrix. Begrijp je dat onderscheid goed, dan wordt R niet alleen logischer, maar kun je ook beter inschatten welke datastructuur in een analyse of modelpipeline het meest passend is.

Klaar om dit soort concepten echt in de vingers te krijgen en toe te passen in je eigen werk? Dan is de Opleiding R precies wat je zoekt.

by: