Laboration 0: Del 2 Benjamin Kjellson 2016–03–21 Introduktion till matriser, vektorer, och ekvationssystem I den här filen får ni en kort introduktion till hur man hanterar och räknar med matriser i R, vilket ni kommer att ha nytta av i kursens laborationsuppgifter. I kursen Statistisk analys har ni stött på datastrukturen data.frame, vilket är en sorts tabell där kolumnerna kan vara av olika typer—heltal (integer) i en, decimaltal (numeric) i en annan, textsträngar (character) i en tredje, och kanske faktorer (factor) i en fjärde. Matriser är lite annorlunda: i dem måste alla kolumner och rader vara av samma typ, t.ex. numeric. Definiera matriser Ibland måste vi skapa en matris för hand, t.ex. när ni tvingas mata in en som är definierad i en bok eller en labbinstruktion. Låt säga att ni ska definiera matrisen ( ) 1 2 3 A= 4 5 6 i R. Det kan ni göra på följande vis: A <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = TRUE) A # visa matrisen [1,] [2,] [,1] [,2] [,3] 1 2 3 4 5 6 Som första argument till funktionen matrix ger jag datan jag vill ha i matrisen; här skriver jag in vektorn c(1, 2, 3, 4, 5, 6) (som jag också kan få genom att skriva 1:6) på ett sådant sätt att man enkelt ser hur matrisen bör se ut. Jag säger att matrisen ska ha två rader med nrow och tre kolumner med ncol. Dock kommer matrisen inte se ut som jag vill om jag inte också säger till funktionen matrix att data ska fylla ut matrisen radvis (default är att fylla ut kolumnvis). Jämför med matrix(1:6, nrow = 2, ncol = 3) [1,] [2,] [,1] [,2] [,3] 1 3 5 2 4 6 Ibland vill man ha en matris fylld av t.ex. ettor. En sån kan man enkelt skapa utan att behöva ange varje element var för sig. Iställer skriver man bara 1 ettor <- matrix(1, nrow = m, ncol = n) om man vill ha en m × n-matris fylld med ettor, kallad ettor. Vill man skapa en diagonalmatris kan man göra det med funktionen diag, som i följande exempel: diag(1:3, nrow = 5, ncol = 3) [1,] [2,] [3,] [4,] [5,] [,1] [,2] [,3] 1 0 0 0 2 0 0 0 3 0 0 0 0 0 0 Vanligare är att man skapar en kvadratisk diagonalmatris, kanske med samma värde längs hela diagonalen. Ett exempel är enhetsmatrisen: diag(1, nrow = 3, ncol = 3) [1,] [2,] [3,] [,1] [,2] [,3] 1 0 0 0 1 0 0 0 1 Vektorer Vi är vana vid att skapa vektorer genom att t.ex. skriva c(1, 2, 3) eller 1:3. När vi skriver ut en sådan vektor ser det ut på följande vis: 1:3 [1] 1 2 3 Om vi vill kan vi göra om en sådan vektor specifikt till en radvektor eller en kolumnvektor, genom att använda funktionen matrix. Vektorerna räknas då som matriser med en rad eller kolumn, respektive. En radvektor kan skapas genom matrix(1:3, nrow = 1) [1,] [,1] [,2] [,3] 1 2 3 och en kolumnvektor genom matrix(1:3, ncol = 1) [1,] [2,] [3,] [,1] 1 2 3 2 Transponera matriser och vektorer Vill man transponera en matris eller vektor i R så kan man använda funktionen t, som följande exempel illustrerar: A <- matrix(1:6, nrow = 3, ncol = 2, byrow = TRUE) # 3 rader, 2 kolumner t(A) # 2 rader, 3 kolumner [1,] [2,] [,1] [,2] [,3] 1 3 5 2 4 6 Detsamma gäller vektorer: radvektor <- matrix(1:3, nrow = 1) t(radvektor) [1,] [2,] [3,] [,1] 1 2 3 och en kolumnvektor genom kolumnvektor <- matrix(1:3, ncol = 1) t(kolumnvektor) [1,] [,1] [,2] [,3] 1 2 3 För vektorer definierade på vanligt vis, genom t.ex. funktionen c eller :, så ser vi att transponaten av dem blir radvektorer: t(1:5) [1,] [,1] [,2] [,3] [,4] [,5] 1 2 3 4 5 Transponerar vi dem två gånger, vilket bör ge oss det vi startade med, får vi alltså en kolumnvektor: t(t(1:5)) [1,] [2,] [3,] [4,] [5,] [,1] 1 2 3 4 5 3 Hämta element ur matriser och vektorer (slicing) Vektorer Ibland vill man hämta ut ett eller flera element ur en vektor eller matris. Låt säga att vi har vektorn v <- 11:15 v # visa vektorn [1] 11 12 13 14 15 Säg att vi nu vill hämta ut det första elementet i vektorn. Det kan vi göra genom att skriva v[1] [1] 11 Index för vektorer, matriser osv. börjar på 1 i R, så v[1] är det första elementet i v, v[2], är det andra, osv. Ett sätt att få det sista elementet är att skriva v[length(v)]. Vill vi hämta alla element förutom det första i v så ger vi ett negativt index: v[-1] [1] 12 13 14 15 Detsamma gäller om vi vill hämta t.ex. alla förutom det första och det andra: v[-c(1, 2)] [1] 13 14 15 Vektorn -c(1, 2) är densamma som c(-1, -2) eftersom minustecknet multipliceras in som -1 i vektorn. Akta er dock för att skriva v[-1:2] eftersom vektorn som skapas av -1:2 inte är densamma som c(-1, -2), som man kanske kan tro, utan är istället c(-1, 0, 1, 2), och att försöka köra v[-1:2] kommer att resultera i ett fel (Error). Matriser Vi kan hämta element ut matriser på liknande sätt. Har vi en matris A och skriver A[i, j] så kommer elementet på rad i och kolumn j att hämtas. Skriver vi A[c(i, k), j] så hämtas elementen på rad i och rad k, i kolumn j, som en vektor. Skriver vi A[c(i, k), c(j, m)] så får vi stället en 2 × 2-matris, och det går givetvis att generalisera detta till indexvektorer (som t.ex. c(i, k) ovan) av större längd än 2. Ibland vill man hämta ut en hel rad eller kolumn ur en matris som en vektor. Det kan man göra genom att lämna ett tomt index, som följande exempel illustrerar 4 A <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = TRUE) A # visa matrisen [1,] [2,] [,1] [,2] [,3] 1 2 3 4 5 6 Hämta ut rad 2 som en vektor: A[2, ] # notera det tomma indexet för kolumner [1] 4 5 6 Hämta ut kolumn 3 som en vektor: A[, 3] # notera det tomma indexet för rader [1] 3 6 Matrismultiplikation För att multiplicera en m×n-matris A med en n×k matris B så använder vi matrismultiplikationsoperatorn %*% i R, som följande exempel demonstrerar: A <- matrix(1:6, nrow = 3, ncol = 2, byrow = TRUE) B <- matrix(0:3, nrow = 2, ncol = 2, byrow = TRUE) A %*% B [1,] [2,] [3,] [,1] [,2] 4 7 8 15 12 23 Att multiplicera med vektorer fungerar på samma vis. Vill vi multiplicera med en vektor på höger sida skriver vi t.ex. v <- 1:2 A %*% v [1,] [2,] [3,] [,1] 5 11 17 Vi hade fått samma resultat om vi hade definierat v <- matrix(1:2, ncol = 1). Multiplikation på vänster sida fungerar likadant: 5 v <- matrix(1:3, nrow = 1) # radvektor v %*% A [1,] [,1] [,2] 22 28 Här hade vi alltså fått samma resultat om vi hade skrivit v <- 1:3. Ekvationssystem Vill vi lösa ekvationssystemet Ax = y, där A är en m × m-matris, x är en m × 1-vektor (kolumnvektor) och y är en m × 1-vektor, så använder vi funktionen solve i R, som följande exempel visar: A y x x <- matrix(1:4, nrow = 2, ncol = 2, byrow = TRUE) <- c(-1, 3) <- solve(A, y) # visa lösningen [1] 5 -3 Prova att lösa systemet för hand och se om du får samma lösning x. Egenvärden och egenvektorer Om A är en kvadratisk matris så kallas (det möjligen komplexa) talet λ för ett egenvärde till A om det finns en vektor v av passande längd sådan att Av = λv. Vektorn v är egenvektorn som svarar mot egenvärdet λ. Detta kanske ni minns från linjär algebra. Vi kan enkelt räkna ut egenvärden och motsvarande egenvektorer i R, genom att använda funktionen eigen. Följande exempel demonstrerar: A <- matrix(c(1, 2, 0, 3), nrow = 2, ncol = 2, byrow = TRUE) egen_lista <- eigen(A) # Funktionen returnerar en lista egen_varden <- egen_lista$values egen_vektorer <- egen_lista$vectors Det första egenvärdet är alltså egen_varden[1] [1] 3 och motsvarande egenvektor hittas i den första kolumnen av matrisen egen_vektorer: egenvektor1 <- egen_vektorer[, 1] egenvektor1 [1] 0.7071068 0.7071068 6 Egenvektorerna som funktionen eigen ger är normaliserade på sådant sätt att deras längd är lika med 1. Som ni kanske minns från linjär algebra så är en egenvektorer inte unika. Om v1 är en egenvektor som motsvarar egenvärdet λ1 till matrisen A, så är också cv1 en egenvektor motsvarande samma egenvärde, för c ̸= 0. Som vi såg ovan var elementen i egenvektorn egenvektor1 identiska. Kanske det vore snyggare om vi multiplicerade/delade egenvektor1 med ett tal som gör att båda elementen tar värdet 1 istället: egenvektor1 <- egenvektor1 / egenvektor1[1] egenvektor1 [1] 1 1 Ett annat alternativ vore att låta summan av elementen i egenvektor1 vara t.ex. lika med 1. Detta kan vi åstadkomma på följande sätt: egenvektor1 <- egenvektor1 / sum(egenvektor1) egenvektor1 [1] 0.5 0.5 Skriva matriser i LaTeX Följande exempel visar hur man skriver en matris i LaTeX. Du kan alltså kopiera “koden” nedan till ett R Markdown-dokument och sedan knitta. $$ \mathbf{P} = \begin{pmatrix} 0 & 0.25 & 0.75 \\ 0.16 & 0.01 & 0.83 \\ 0.24 & 0.47 & 0.29 \end{pmatrix} $$ Detta kommer synas som 0 0.25 P = 0.16 0.01 0.24 0.47 0.75 0.83 0.29 Vill man ha matriser med hakparenteser, dvs [ ], istället, så kan man skriva bmatrix istället för pmatrix. Övningsuppgifter Uppgift 1 Med kod, definiera matrisen ( A= 1 2 −1 1 7 ) genom att använda funktionen matrix och matrisen ( ) 1 0 D= 0 −1 genom att använda funktionen diag, och bilda sedan matrisen C = A′ D, där A′ är transponatet av A. Dubbelkolla resultatet genom att utföra uträkningen för hand. Uppgift 2 Lös följande ekvationssystem genom att definiera en matris A och en vektor y, och använda funktionen solve för att hitta lösningen (vektorn) x = (x1 , x2 , x3 )′ : 2x1 + x2 + 3x3 = 1 2x1 + 6x2 + 8x3 = 3 6x1 + 8x2 + 18x3 = 5 Jämför med lösningen du får när du löser systemet för hand. Uppgift 3 Om A är en kvadratisk matris, så kan vi definiera potenser av A rekursivt genom A1 = A och An+1 = AAn för n > 1. Vi skulle också kunna definiera A0 = I, där I är enhetsmatrisen. Skapa nu en funktion mpower <- function(A, n) { ... } som tar som argument en (kvadratisk) matris A och ett heltal n större än (eller lika med—ditt val) 0, och returnerar A upphöjt till n i överensstämmelse med definitionen ovan. OBS! Din funktion behöver dock inte vara rekursiv, som i definitionen som gavs ovan. Den kan lika gärna vara iterativ, i vilket fall du kanske behöver använda dig av någon slags loop. Prova gärna att skriva både en rekursiv och en iterativ funktion. 8