Charlie Lindgren, Doktorand i Mikrodata Analys
8 Maj 2017
Linjära ekvationer såsom
\[ 2*x = 20 \]
kan vi enkelt lösa i R. Ekvationen ovan är ju väldigt lätt att lösa, men såklart kan man lösa mer komplicerade ekvationer.
I R kan vi direkt lösa denna ekvation som nedan
a <- 2
b <- 20
solve(a,b)
[1] 10
Då har vi alltså löst ekvationen
\[ 2*x = 20 \]
Vill ni utveckla detta till två ekvationer med två obekanta såsom nedan
\[ x + y = 1 \] \[ -x + y = -2 \]
så kan vi även skriva kod för detta i R.
Koden för att lösa ett sådant ekvationssystem skrivs enklast som nedan
a <- rbind(c(1,1),
c(-1,1))
b <- c(1,-2)
solve(a,b)
[1] 1.5 -0.5
Det ekvationssystem som vi nyss löste går att skapa grafer för, vi skriver om ekvationerna med \( y \) på vänster sida
\[ y = 1 - x \] \[ y = -2 + x \]
curve(1-x, xlim=c(-1,5),ylim=c(-2,2))
curve(-2+x,add=TRUE)
abline(v=0,h=0,lty="dashed")
Vi kan försöka lösa ännu ett ekvationssystem
\[ 3x + 6y = 3 \] \[ 2x + 4y = 0 \]
a <- rbind(c(3,6),
c(2,4))
b <- c(3,0)
solve(a,b)
Det kommer inte att gå lika bra då man får följande felmeddelande
Error in solve.default(a, b) :
Lapack routine dgesv: system is exactly singular: U[2,2] = 0
Singuläriteten som uppstår beror på att det inte finns någon lösning till ekvationssystemet. Kurvorna kommer aldrig att skära varandra, vilket innebär att de är parallella.
Detta kan vi enklast se om vi skriver om kurvorna
\[ y = \frac{3}{6} - \frac{3}{6}x \] \[ y = -\frac{2}{4}x \]
curve(3/6 - 3/6*x, xlim=c(-1,5),ylim=c(-2,2))
curve(-2/4*x,add=TRUE)
abline(v=0,h=0,lty="dashed")
Vi kan även lösa större ekvationssystem. Ta tillexempel
\[ x + y + z = 0 \] \[ x - y + z = 0 \] \[ x - y - z = 0.8 \]
vilket vi löser genom att skriva
a <- rbind(c(1,1,1),
c(1,-1,1),
c(1,-1,-1))
b <- c(0,0,0.8)
solve(a,b)
[1] 0.4 0.0 -0.4
Följande kod återskapar en 3D graf över lösningen, kör denna, förstora och flytta runt för att se lösningen bättre! Högre dimensioner går inte att göra grafer av såhär
install.packages("rgl")
library(rgl)
# Skapa lite "dummy" data
dat <- replicate(2, 1:3)
# En tom 3D graf
plot3d(dat, type = 'n', xlim = c(-1, 1), ylim = c(-1, 1), zlim = c(-3, 3), xlab = '', ylab = '', zlab = '')
# Skapa grafer över de plan som vi vill visa
planes3d(1, 1, 1, 0, col = 'red', alpha = 0.6)
planes3d(1, -1, 1, 0, col = 'orange', alpha = 0.6)
planes3d(1, -1, -1, -0.8, col = 'blue', alpha = 0.6)
En styrka med R är att programmeringsspråk är väl anpassat till att manipulera matriser.
Ta tillexempel
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{pmatrix} \]
där vi har \( a \) och \( c \) i första kolumnen samt \( b \) och \( d \) i andra kolumnen. Sedan har vi \( a \) och \( b \) på första raden samt \( c \) och \( d \) på andra raden. Detta är en \( 2x2 \) matris.
Vi kan återskapa denna matris i R
matrix(c("a","b",
"c","d"),
byrow=TRUE, nrow=2,ncol=2)
[,1] [,2]
[1,] "a" "b"
[2,] "c" "d"
alternativt genom att skriva
rbind(c("a","b"),
c("c","d"))
cbind(c("a","c"),
c("b","d"))
[,1] [,2]
[1,] "a" "b"
[2,] "c" "d"
Vilket sätt ni än använder är mer en smaksak. Självklart kan vi ange denna matris med siffror, vilket såklart blir mer användbart vid uträkningar
matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
[,1] [,2]
[1,] 1 2
[2,] 3 4
Men bokstäver kan vara rätt användbart för att visa hur vissa funktioner sker.
Låt oss ta transposen av matrisen med bokstäver
abc_matris <- matrix(c("a","b",
"c","d"),
byrow=TRUE, nrow=2,ncol=2)
t(abc_matris)
[,1] [,2]
[1,] "a" "c"
[2,] "b" "d"
Funktionen transpose byter alltså plats på rader och kolumner!
Vi kan också utföra uträkningar mellan matriser, ta exemplet nedan
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{pmatrix} * \begin{pmatrix} \begin{matrix} e & f \\ g & h \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} a*e + b*g & a*f + b*h \\ c*e + d*g & c*f + d*h \end{matrix} \end{pmatrix} \]
Vilket återger matrismultiplikationen mellan två matriser av samma storlek.
Matrismultiplikationen i R måste dock visas med siffror, så vi gör detta
matris1 <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
matris2 <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
matris1 %*% matris2
[,1] [,2]
[1,] 7 10
[2,] 15 22
Notera att multiplikationen mellan matriser i förgående exempel gick pågrund av att matriserna var av rätt storlek. Generellt sett så skall den första matrisens kolumner vara lika stor som den andra matrisens rader, och utfallet kommer att bli en matris med lika många rader som i den första matrisen samt lika många kolumner som i den andra matrisen.
\[ (4x \color{red}{2})(\color{red}{3}x2) \] ej möjligt
\[ (4x \color{green}{2})(\color{green}{2}x3) \] ger en \( (4x3) \) matris
Nedan visar jag hur en uträkning för sådana matriser kan se ut
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \\ e & f \end{matrix} \end{pmatrix} * \begin{pmatrix} \begin{matrix} g & h & i \\ j & k & l \end{matrix} \end{pmatrix} \]
\[ = \begin{pmatrix} \begin{matrix} a*g + b*j & a*h + b*k & a*i + b*l \\ c*g + d*j & c*h + d*k & c*i + d*l \\ e*g + f*j & e*h + f*k & e*i + f*l \end{matrix} \end{pmatrix} \]
Och vi räknar i R
matris1 <- matrix(c(1,2,
3,4,5,6),
byrow=TRUE, nrow=3,ncol=2)
matris2 <- matrix(c(1,2,
3,4,5,6),
byrow=TRUE, nrow=2,ncol=3)
matris1 %*% matris2
[,1] [,2] [,3]
[1,] 9 12 15
[2,] 19 26 33
[3,] 29 40 51
Vi kan även addera och subtrahera matriser, nedan visar jag ett exempel på addition
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{pmatrix} + \begin{pmatrix} \begin{matrix} e & f \\ g & h \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} a + e & b + f \\ c + g & d + h \end{matrix} \end{pmatrix} \]
Matriserna adderas alltså positionsvis.
I R är detta såklart väldigt enkelt att skriva
matris1 <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
matris2 <- matrix(c(5,6,
7,8),
byrow=TRUE, nrow=2,ncol=2)
matris1 + matris2
[,1] [,2]
[1,] 6 8
[2,] 10 12
Men nu måste däremot matriserna vara lika stora.
Låt oss titta på ekvationssystemet
\[ x + 2y = 1 \\ 3x + 4y = 2 \]
Detta kan även skrivas i matrisform
\[ \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix} * \begin{pmatrix} \begin{matrix} x \\ y \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} 1 \\ 2 \end{matrix} \end{pmatrix} \]
Vi kan självklart lösa ekvationssystemet med den funktion vi redan har lärt oss. Men vi kan även även använda matriserna. Inversen av en \( 2x2 \) matris ges av
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{pmatrix}^{-1} = \frac{1}{ad - bc} \begin{pmatrix} \begin{matrix} d & -b \\ -c & a \end{matrix} \end{pmatrix} \]
Detta resultat kan vi använda för att lösa ekvationen.
Hur då? Jo genom att ta inversen kan vi flytta över matrisen till andra sidan och ha kvar \( x \) och \( y \) som vi söker. Lösningarna till dessa får vi då ut som ekvationer
\[ \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix}^{-1} \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix} \begin{pmatrix} \begin{matrix} x \\ y \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix}^{-1} \begin{pmatrix} \begin{matrix} 1 \\ 2 \end{matrix} \end{pmatrix} \]
\[ \begin{pmatrix} \begin{matrix} x \\ y \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix}^{-1} \begin{pmatrix} \begin{matrix} 1 \\ 2 \end{matrix} \end{pmatrix} \]
Inversen som vi vill lösa blir således
\[ \begin{pmatrix} \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \end{pmatrix}^{-1} = \frac{1}{1*4 - 2*3} \begin{pmatrix} \begin{matrix} 4 & -2 \\ -3 & 1 \end{matrix} \end{pmatrix} \]
\[ = -\frac{1}{2} \begin{pmatrix} \begin{matrix} 4 & -2 \\ -3 & 1 \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} -2 & 1 \\ \frac{3}{2} & -\frac{1}{2} \end{matrix} \end{pmatrix} \]
Självklart kan man lösa inversen snabbt i R.
matris <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
solve(matris)
[,1] [,2]
[1,] -2.0 1.0
[2,] 1.5 -0.5
Det finns finurliga funktioner i R. Med hjälp av \( \texttt{MASS} \) paketet kan vi skapa kvottal istället för decimaler så vi kan jämföra uträkningarna lättare
install.packages("MASS")
library(MASS)
matris <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
fractions(solve(matris))
[,1] [,2]
[1,] -2 1
[2,] 3/2 -1/2
Med vår invers så kan vi nu skriva ut svaret på ekvationsystemet
\[ \begin{pmatrix} \begin{matrix} x \\ y \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} -2 & 1 \\ \frac{3}{2} & -\frac{1}{2} \end{matrix} \end{pmatrix} \begin{pmatrix} \begin{matrix} 1 \\ 2 \end{matrix} \end{pmatrix} \]
\[ = \begin{pmatrix} \begin{matrix} -2 * 1 + 1 * 2 \\ \frac{3}{2} * 1 + (-\frac{1}{2} * 2) \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} -2 + 2 \\ \frac{3}{2} + (-1) \end{matrix} \end{pmatrix} = \begin{pmatrix} \begin{matrix} 0 \\ \frac{1}{2} \end{matrix} \end{pmatrix} \]
I R ser detta ut som nedan
library(MASS)
matris <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
fractions(solve(matris)%*%c(1,2))
[,1]
[1,] 0
[2,] 1/2
Determinanten av en \( 2x2 \) matris
\[ \begin{pmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{pmatrix} \]
ges av
\[ \begin{Vmatrix} \begin{matrix} a & b \\ c & d \end{matrix} \end{Vmatrix} = a*d - b*c \]
Som man kan känna igen från uträkningen av inversen.
I R återges detta helt enkelt av
matris <- matrix(c(1,2,
3,4),
byrow=TRUE, nrow=2,ncol=2)
det(matris)
[1] -2
Vilket ni själva kan verifiera. Notera att determinanten är vad vi kallar en skalär, helt enkelt ett tal och inte en matris med flera element!