Ta strona wykorzystuje ciasteczka ("cookies") w celu zapewnienia maksymalnej wygody w korzystaniu z naszego serwisu. Czy wyrażasz na to zgodę?

Czytaj więcej
< All Topics
Print

Macierze

Tworzenie macierzy

Macierze to dwuwymiarowe tablice złożone z danych tego samego typu. Można je utworzyć z każdego ciągu złożonego z n×k elementów za pomocą instrukcji matrix(ciag,nrow=n,ncol=k) zaznaczając w ten sposób, że macierz ma mieć n wierszy i k kolumn. Dane są dzielone wzdłuż kolumn od góry w dół, a kolumny układane od lewej do prawej.

> ciag=rep(1:4,3)
> matrix(ciag, ncol=4, nrow=3)
[,1] [,2] [,3] [,4]
[1,]    1    4    3    2
[2,]    2    1    4    3
[3,]    3    2    1    4
> matrix(ciag, nrow=4, ncol=3)
[,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3
[4,]    4    4    4
> matrix(ciag,6,4)
[,1] [,2] [,3] [,4]
[1,]    1    3    1    3
[2,]    2    4    2    4
[3,]    3    1    3    1
[4,]    4    2    4    2
[5,]    1    3    1    3
[6,]    2    4    2    4
> matrix(ciag,5,3)
[,1] [,2] [,3]
[1,]    1    2    3
[2,]    2    3    4
[3,]    3    4    1
[4,]    4    1    2
[5,]    1    2    3
Warning message:
In matrix(ciag, 5, 3) :
data length [12] is not a sub-multiple or multiple of the number of rows [5]

 

Kolejne elementy wektora wypełniają kolumny od góry do dołu i proces wypełniania przechodzi na następna kolumnę. Gdy liczba elementów ciągu jest mniejsza niż komórek w macierzy po dojściu do końca wektora kolejne komórki wypełnią się elementami wektora począwszy od pierwszego elementu. Wszystko jest dobrze, gdy liczba komórek w macierzy jest wielokrotnością liczby elementów w wektorze. Gdy nie jest spełniony ten warunek R generuje komunikat ostrzegawczy, ale macierz tworzy. Można ją zapamiętać pod wybraną nazwą i posługiwać się nią, jako obiektem typu macierz.

Nazwy opcji nrow, ncol mogą być pominięte. Wtedy pierwszą z liczb traktuje się domyślnie jako nrow, a druga jako ncol. Można też skrócić definicje macierzy do formuły matrix(ciąg, ncol=n) lub matrix(ciag,nrow=k).

Czasami wygodnie jest wypełniać macierz elementami wektora rzędami, nie kolumnami. Należy wtedy dopisać opcję byrow=TRUE (byrow=T lub byrow=1) w funkcji matrix().

> ciag=1:10
> matrix(ciag,2,5)
[,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
> matrix(ciag,2,5,byrow=TRUE)
[,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10

 

Macierze można tworzyć przez sklejanie wektorów o jednakowej liczbie elementów za pomocą funkcji cbind() (wtedy składowe wektory są kolumnami) lub rbind() (wtedy sklejane wektory są wierszami). Kiedy wektory nie są równej długości, obowiązuje zasada równania do dłuższego wektora poprzez cykliczne powtarzanie wyrazów z krótszego wektora.

> cbind(1:6, rep(3,6), c(2,4,5,3,8,2))
[,1] [,2] [,3]
[1,]    1    3    2
[2,]    2    3    4
[3,]    3    3    5
[4,]    4    3    3
[5,]    5    3    8
[6,]    6    3    2
> rbind(1:6, rep(3,6), c(2,4,5,3,8,2))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    3    4    5    6
[2,]    3    3    3    3    3    3
[3,]    2    4    5    3    8    2
> rbind(1:6, 1:2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    3    4    5    6
[2,]    1    2    1    2    1    2

 

Funkcja outer() pozwala na tworzenie macierzy wypełnianych liczbami zgodnie z wartościami wybranej funkcji, w domyśle jest to funkcja f(x,y)=x*y.

> outer(1:3,1:5)
[,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
> outer(rep(7,3),c(3,1,2))
[,1] [,2] [,3]
[1,]   21    7   14
[2,]   21    7   14
[3,]   21    7   14

 

Działanie w funkcji outer() można zmienić dopisując opcje “+”, “/” itd albo zdefiniować własną funkcję wg schematu:

f(x,y) wyrażenie matematyczne

> outer(1:3,1:5,"+")
[,1] [,2] [,3] [,4] [,5]
[1,]    2    3    4    5    6
[2,]    3    4    5    6    7
[3,]    4    5    6    7    8
> outer(1:3,1:5, function(x,y) log(x^2+y^2))
     [,1]     [,2]     [,3]     [,4]     [,5]
[1,] 0.6931472 1.609438 2.302585 2.833213 3.258097
[2,] 1.6094379 2.079442 2.564949 2.995732 3.367296
[3,] 2.3025851 2.564949 2.890372 3.218876 3.526361

 

 

Nazywanie wierszy i kolumn macierzy

Przydatną opcją przy tworzeniu macierzy może okazać się “dimnames”. Pozwala ona na nazwanie wierszy i kolumn macierzy odpowiednimi nazwami. Jej wartością jest lista ciągów nazw. Nazwy te nie stają się obiektami R.

> ciag=1:10
> matrix(ciag,2,5,dimnames=list(c("rząd1", "rząd2"),
+ c("kol1", "kol2", "kol3", "kol4", "kol5" )))
kol1 kol2 kol3 kol4 kol5
rząd1   1    3    5    7    9
rząd2   2    4    6    8   10

 

Mając nazwane wiersze i kolumny można odwoływać się do wartości macierzy używając składni:

> macierz=matrix(`1:10,2,5,dimnames=list(c("rząd1", "rząd2"),
+ c("kol1", "kol2", "kol3", "kol4", "kol5" )))
> macierz["rząd2","kol3"]
[1] 6
> macierz=matrix(`1:10,2,5,dimnames=list(c("rząd1", "rząd2"),
+ c("kol3", "kol2", "kol3", "kol2", "kol3" )))
> macierz["rząd2","kol3"]
[1] 2

 

Nazwy kolumn albo wierszy mogą się powtarzać, ale odwołując się poprzez nazwy do wartości macierzy uzyskujemy tylko pierwszą z możliwych wartości.

Jednocześnie obok opcji dimnames istnieje funkcja dimnames(). Jej argumentem jest macierz z nazwanymi wierszami i kolumnami, a wartością – lista nazw wierszy i kolumn macierzy.

> ciag=1:10
> macierz=matrix(ciag,2,5,dimnames=list(c("rząd1", "rząd2"),
+ c("kol1", "kol2", "kol3", "kol4", "kol5" )))
> dimnames(macierz)
[[1]]
[1] "rząd1" "rząd2"

[[2]]
[1] "kol1" "kol2" "kol3" "kol4" "kol5"

 

Mając macierz z nazwanymi wierszami i kolumnami można sprawdzić, który wiersz albo kolumna mają daną nazwę:

> ciag=1:10
> macierz=matrix(ciag,2,5,dimnames=list(c("rząd1", "rząd2"),
+ c("kol1", "kol2", "kol3", "kol4", "kol5" )))
> #badamy nazwy wierszy kolumny liczby znajdującej się w drugim wierszu i trzeciej kolumnie.
> dimnames(macierz)[[1]][2]
[1] "rząd2"
> dimnames(macierz)[[2]][3]
[1] "kol3"

 

 

Macierze zaimplementowane do R

Prostą macierzą jest USPersonalExpenditure zawierającą wykaz wydatków (w milionach dolarów) na wyroby zaliczane do 5 różnych kategorii ponoszonych przez Amerykanów w latach 1940, 1945, 1950, 1955 i 1960.

> USPersonalExpenditure
                     1940   1945  1950 1955  1960
Food and Tobacco    22.200 44.500 59.60 73.2 86.80
Household Operation 10.500 15.500 29.00 36.5 46.20
Medical and Health   3.530  5.760  9.71 14.0 21.10
Personal Care        1.040  1.980  2.45  3.4  5.40
Private Education    0.341  0.974  1.80  2.6  3.64

 

Macierz WorldPhones pokazuje natomiast liczbę telefonów w różnych częściach świata w latach 1951-1961.

> WorldPhones
    N.Amer Europe Asia S.Amer Oceania Africa Mid.Amer
1951  45939  21574 2876   1815    1646     89      555
1956  60423  29990 4708   2568    2366   1411      733
1957  64721  32510 5230   2695    2526   1546      773
1958  68484  35218 6662   2845    2691   1663      836
1959  71799  37598 6856   3000    2868   1769      911
1960  76036  40341 8220   3145    3054   1905     1008
1961  79831  43173 9053   3338    3224   2005     1076

 

Inną macierzą jest euro.cross pokazujące przelicznik 11 walut europejskich w końcu grudnia 1998 roku. W krajach tych obowiązywały różne waluty poprzedzające wprowadzenie Euro, których oficjalne skróty są nazwami kolumn i wierszy.

> euro.cross
             ATS         BEF         DEM         ESP         FIM         FRF
ATS  1.000000000  2.93161486 0.142135709  12.0917422 0.432093050 0.476702543
BEF  0.341108927  1.00000000 0.048483759   4.1246012 0.147390797 0.162607493
DEM  7.035529673 20.62546336 1.000000000  85.0718109 3.040003477 3.353854885
ESP  0.082701069  0.24244768 0.011754775   1.0000000 0.035734557 0.039423810
FIM  2.314316324  6.78468413 0.328946992  27.9841163 1.000000000 1.103240477
FRF  2.097744212  6.14977811 0.298164361  25.3653822 0.906420695 1.000000000
IEP 17.471976881 51.22110711 2.483391826 211.2666399 7.549519785 8.328935807
ITL  0.007106602  0.02083382 0.001010102   0.0859312 0.003070713 0.003387735
LUF  0.341108927  1.00000000 0.048483759   4.1246012 0.147390797 0.162607493
NLG  6.244151907 18.30544854 0.887516960  75.5026750 2.698054644 2.976603092
PTE  0.068636087  0.20121457 0.009755639   0.8299299 0.029657176 0.032718997
IEP         ITL         LUF         NLG         PTE
ATS 0.0572345080  140.714229  2.93161486 0.160149851  14.5695951
BEF 0.0195232016   47.998880  1.00000000 0.054628544   4.9698190
DEM 0.4026750791  989.999131 20.62546336 1.126739032 102.5048189
ESP 0.0047333550   11.637217  0.24244768 0.013244564   1.2049211
FIM 0.1324587561  325.657236  6.78468413 0.370637415  33.7186519
FRF 0.1200633578  295.182459  6.14977811 0.335953424  30.5632839

 

Inną macirzą (bardzo dużą) zaimplementowaną do R jest volcano. Pokazuje ona wysokość względną wzniesienia terenu wokół wulkanu Maungawhau na Nowej Zelandii dla współrzednych wyznaczanych co 10 m. Macierz ta używana jest do testowania w R funkcji graficznych stosowanych w kartografii.

Odwoływanie się do poszczególnych elementów macierzy

Do poszczególnych komórek macierzy odwołujemy się zgodnie ze schematem: macierz[i,j] gdzie i jest numerem wiersza a j numerem kolumny. Odwołanie macierz[,j] oznacza ciąg złożony z wyrazów j-tej kolumny, a macierz[i,] oznacza ciąg złożony z i-tego wiersza. Aby ciągi macierz[i,] i macierz[,j] traktowane były jako macierze z jednym wierszem lub jedną kolumną konieczna jest opcja drop=FALSE.

> ciag=c(2.1, 3.4, 5.6, 2.8, 3.1, 6.0, 2.9, 3.5, 5.1, 2.1, 3.8, 5.4)
> macierz=matrix(ciag,3,4)
> macierz
     [,1] [,2] [,3] [,4]
[1,]  2.1  2.8  2.9  2.1
[2,]  3.4  3.1  3.5  3.8
[3,]  5.6  6.0  5.1  5.4
> macierz[2,2]
[1] 3.1
> macierz[2,]
[1] 3.4 3.1 3.5 3.8
> macierz[2,,drop=FALSE]
     [,1] [,2] [,3] [,4]
[1,]  3.4  3.1  3.5  3.8

 

Odwoływać się można do kilku elementów na raz poprzez tworzenie ciągów w zbiorze indeksów. Ważne by te indeksy nie wyszły poza zakres macierzy.

> mat=matrix(1:12,3,4)
> mat
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> mat[1:2,c(2,4)]
     [,1] [,2]
[1,]    4   10
[2,]    5   11
> mat[,2:4]
     [,1] [,2] [,3]
[1,]    4    7   10
[2,]    5    8   11
[3,]    6    9   12
> mat[c(1,3),]
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    3    6    9   12
> mat[,4:6]
Błąd w poleceniu 'mat[, 4:6]':indeks jest poza granicami

 

Gdy wiersze lub/i kolumny macierzy zostały nazwane można (ale nie obowiązkowo) odwoływać się poprzez te nazwy do poszczególnych elementów macierzy.

> mac=matrix(letters[1:12],4,3,dimnames=list(c("A","AA","AAA","AAAA"),c("B","BB","BBB")))
> mac
     B   BB  BBB
A    "a" "e" "i"
AA   "b" "f" "j"
AAA  "c" "g" "k"
AAAA "d" "h" "l"
> mac["AA","BBB"]
[1] "j"
> mac["AA",]
  B  BB BBB
"b" "f" "j"
> mac[,"BBB"]
  B  BB BBB
"b" "f" "j"
> mac["C",]
Błąd w poleceniu 'mac["C", ]':indeks jest poza granicami

 

Odwołanie się do samych nazw wierszy i kolumn umożliwia funkcja dimnames().

> mac=matrix(1:12,4,3,dimnames=list(letters[1:4],LETTERS[1:3]))
> mac
  A B  C
a 1 5  9
b 2 6 10
c 3 7 11
d 4 8 12
> dimnames(mac)
[[1]]
[1] "a" "b" "c"
#
[[2]]
[1] "A" "B" "C" "D"
#

 

Edycja i modyfikowanie macierzy

Zamienienie wartości jednego z elementów macierzy odbywa się poprzez podstawienie macierz[i,j]=x. Można zamieniać całe kolumny lub wiersze na inne wektory.

> macierz=matrix(1:9,3,3)
> macierz
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> macierz[1,]=c(7,6,5)
> macierz
     [,1] [,2] [,3]
[1,]    7    6    5
[2,]    2    5    8
[3,]    3    6    9
> macierz[,1]=c(7,6,5)
> macierz
     [,1] [,2] [,3]
[1,]    7    6    5
[2,]    6    5    8
[3,]    5    6    9

 

Poprzez operacje na indeksach wyrazów można przestawiać wiersze i wyrazy macierzy.

> macierz=matrix(1:9,3,3)
> macierz
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> macierz1=macierz[3:1,]
> macierz1
     [,1] [,2] [,3]
[1,]    3    6    9
[2,]    2    5    8
[3,]    1    4    7
> macierz2=macierz[,3:1]
> macierz2
     [,1] [,2] [,3]
[1,]    7    4    1
[2,]    8    5    2
[3,]    9    6    3

 

Usunięcie wybranych wierszy lub kolumn można zrealizować poprzez wymienienie wierszy/kolumn, które mają pozostać albo wierszy lub kolumn, które mają być usunięte.

> macierz=matrix(1:9,3,3)
> macierz
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> macierz1=macierz[c(1,3),]
> macierz1
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    3    6    9
> macierz2=macierz[-2,]
> macierz2
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    3    6    9
> macierz3=macierz[,c(1,3)]
> macierz3
     [,1] [,2]
[1,]    4    7
[2,]    5    8
[3,]    6    9
> macierz4=macierz[,-2]
> macierz4
     [,1] [,2]
[1,]    4    7
[2,]    5    8
[3,]    6    9

 

Dodanie kolumn do macierzy lub poziome łączenie kilku macierzy w jedną macierz można zrealizować funkcją cbind().

> mat1=matrix(1:6,2,3)
> mat1
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> mat2=matrix(c(7,8),2,3)
> mat2
     [,1] [,2] [,3]
[1,]    7    7    7
[2,]    8    8    8
> cbind(mat1,c(7,8,9))
> cbind(mat1,c(7,8,9))
     [,1] [,2] [,3] [,4]
[1,]    1    3    5    7
[2,]    2    4    6    8
Komunikat ostrzegawczy:
W poleceniu 'cbind(mat1, c(7, 8, 9, 10))':
number of rows of result is not a multiple of vector length (arg 2)
> cbind(c(7,8,9,10),mat1)
     [,1] [,2] [,3] [,4]
[1,]    7    1    3    5
[2,]    8    2    4    6
Komunikat ostrzegawczy:
W poleceniu 'cbind(mat1, c(7, 8, 9, 10))':
number of rows of result is not a multiple of vector length (arg 2)
> cbind(mat1,mat2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    3    5    7    7    7
[2,]    2    4    6    8    8    8
> mat2=matrix(c(7,8,9),3,3)
> mat2
     [,1] [,2] [,3]
[1,]    7    7    7
[2,]    8    8    8
[3,]    9    9    9
> cbind(mat1,mat2)
Błąd w poleceniu 'cbind(mat1, mat2)': liczby wierszy macierzy muszą być zgodne (zobacz argument 2)

 

Przy dołączaniu kolumny w postaci wektora liczba wierszy ustala się poprzez liczbę wierszy w macierzy i liczba elementów wektora jest obcięta albo zaczyna się sukcesywnie powtarzać. Natomiast łączenie poziome macierzy o różnej liczbie wierszy nie jest możliwe.

Dodanie wiersza do macierzy albo pionowe połączenie dwóch macierzy można zrealizować funkcją rbind().

> mat1=matrix(1:6,2,3)
> mat1
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> mat2=matrix(c(7,8),2,3)
> mat2
     [,1] [,2] [,3]
[1,]    7    7    7
[2,]    8    8    8
> rbind(mat1,c(7,8))
> mat2
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
[3,]    7    8    7
Komunikat ostrzegawczy:
W poleceniu 'rbind(mat1, c(7, 8))':
number of rows of result is not a multiple of vector length (arg 2)
> rbind(mat1,mat2)
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
[1,]    7    7    7
[2,]    8    8    8

 

Dołączanie wiersza do macierzy za pomocą funkcji rbind() o innej liczbie elementów niż liczba kolumn w macierzy powoduje dopasowanie liczby jego elementów do liczby kolumn macierzy: ich wielokrotne powtarzanie lub obcięcie. Połączenie dwóch macierzy o nierównej liczbie kolumn nie jest możliwe.

Modyfikowanie nazw wierszy i kolumn można zrealizować za pomocą funkcji dimnames(). Należy nowe wartości wprowadzić w postaci listy, albo modyfikować poszczególne elementy listy dimnames(macierz). Ponadto polecenie dimnames(macierz)=NULL usuwa wszystkie nazwy kolumn i wierszy.

> mat=matrix(1:9,3,3,dimnames=list(1:3,1:3))
> mat
  1 2 3
1 1 4 7
2 2 5 8
3 3 6 9
> dimnames(mat)[[1]]=c("L1","L2","L3")
> mat
   1 2 3
L1 1 4 7
L2 2 5 8
L3 3 6 9
> dimnames(mat)[[2]]=c("C1","C2","C3")
> mat
   C1 C2 C3
L1  1  4  7
L2  2  5  8
L3  3  6  9
> dimnames(mat)=NULL
> mat
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> dimnames(mat)=list(c("W1","W2","W3"),c("K1","K2","K3"))
> mat
   K1 K2 K3
W1  1  4  7
W2  2  5  8
W3  3  6  9

 

Funkcje i działania na macierzach

Funkcje mode() i typeof() pokazują typ elementów macierzy, funkcja class() pokazuje typ obiektu (dla macierzy daje odpowiedź “matrix”), a funkcja str() pokazuje strukturę macierzy.

> mac1=matrix(1:12,3,4)
> mac1
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> mode(mac1)
[1] "numeric"
> typeof(mac1)
[1] "integer"
> class(mac1)
[1] "matrix"
> str(mac1)
int [1:3, 1:4] 1 2 3 4 5 6 7 8 9 10 ...
> mac2=matrix(letters[1:12],3,4,dimnames=list(1:3,1:4))
> mac2
 1   2   3   4
1 "a" "d" "g" "j"
2 "b" "e" "h" "k"
3 "c" "f" "i" "l"
> mode(mac2)
[1] "character"
> typeof(mac1)
[1] "character"
> class(mac2)
[1] "matrix"
> str(mac1)
chr [1:3, 1:4] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l"
- attr(*, "dimnames")=List of 2
..$ : chr [1:3] "1" "2" "3"
..$ : chr [1:4] "1" "2" "3" "4"

 

Podstawowe funkcje związane z macierzami pokazują ich budowę i strukturę. Są to:

  • dim(macierz) – wymiary macierzy – funkcja dwukrotna (liczba wierszy, liczba kolumn).
  • ncol(macierz) – liczba kolumn macierzy.
  • nrow(macierz) – liczba wierszy w macierzy.
  • length(macierz) – liczba elementów w macierzy.
  • dimnames(macierz) – nazwy wierszy i kolumn macierzy w postaci listy)
> mat=matrix(1:10,ncol=2,dimnames=list(letters[1:5],c("K1","K2")))
> dim(mat)
[1] 5 2
> ncol(mat)
[1] 2
> nrow(mat)
[1] 5
> length(mat)
[1] 10
> dimnames(mat)
[[1]]
[1] "a" "b" "c" "d" "e"

[[2]]
[1] "K1" "K2"

> mode(mat)
[1] "numeric"
> str(mat)
int [1:5, 1:2] 1 2 3 4 5 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:5] "a" "b" "c" "d" ...
..$ : chr [1:2] "K1" "K2"

 

Dla macierzy możliwe jest wyświetlanie głównej przekatnej (od górnego lewego rogu w dół po skosie) dzięki funkcji diag(),. Najczęściej operacja ta stosowana jest dla macierzy kwadratowych.

> mac1=matrix(1:12,3,4)
> mac1
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
> diag(mac1)
[1] 1 5 9
> mac2=matrix(1:12,4,3)
> mac2
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12
> diag(mac2)
[1] 1 6 11
> mac3=matrix(1:16,4,4)
> mac3
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16
> diag(mac3)
[1]  1  6 11 16

 

W przypadku macierzy o wielu wierszach ich wyświetlenie w całości w konsoli R nie jest możliwe i niepotrzebne. Czasem jednak potrzebne jest zobaczenie kilku wierszy początkowych, co umożliwia funkcja head(macierz) lub końcowych realizowane za pomocą funkcji tail(macierz).

> mat=matrix(1:100,ncol=2,dimnames=list(c(letters,letters)[1:50],c("K1","K2")))
> head(mat)
  K1 K2
a  1 51
b  2 52
c  3 53
d  4 54
e  5 55
f  6 56
> tail(mat)
  K1  K2
s 45  95
t 46  96
u 47  97
v 48  98
w 49  99
x 50 100

 

Aby operować elementami macierzy jako wektorem można użyć funkcji as.vector(). Funkcja as.matrix() nie jest do niej odwrotna. Zamienia ona wektor na macierz jednokolumnową.

> macierz=matrix(letters[1:6],3,2,dimnames=list(1:3,1:2))
> macierz
   1   2
1 "a" "d"
2 "b" "e"
3 "c" "f"
> as.vector(macierz)
  [1] "a" "b" "c" "d" "e" "f"
> as.matrix(as.vector(macierz))
     [,1]
[1,] "a"
[2,] "b"
[3,] "c"
[4,] "d"
[5,] "e"
[6,] "f" 
> macierz=matrix(letters[1:6],3,2,dimnames=list(1:3,1:2),byrow=TRUE)
> macierz
   1   2
1 "a" "b"
2 "c" "d"
3 "e" "f"
> as.vector(macierz)
  [1] "a" "c" "e" "b" "d" "f"

 

Funkcja as.vector() zastosowana do wielokolumnowych macierzy zawsze tworzy wektor łącząc kolumny ze sobą od pierwszej do ostatniej.

W przypadku macierzy o wartościach liczbowych wiele działań jest dla nich tak samo określonych jak na wektorach. Przykładowo zapis macierz+x, macierz*x, macierz^x oznacza, że dla każdego elementu macierzy dodano x, każdy element pomnożono przez x lub każdy element podniesiono do potęgi x. Analogicznie do działań między wektorami przebiegają działania macierz+wektor, macierz*wektor, macierz^wektor itd.

> mat=matrix(1:6,2,3)
> mat
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> mat+1
     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    3    5    7
> mat+c(1,2)
     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    4    6    8
> mat+c(1,2,3)
     [,1] [,2] [,3]
[1,]    2    6    7
[2,]    4    5    9
> mat+c(1,2,3,4)
     [,1] [,2] [,3]
[1,]    2    6    6
[2,]    4    8    8
Komunikat ostrzegawczy:
W poleceniu 'mat + c(1, 2, 3, 4)':
długość dłuszego obiektu nie jest wielokrotnością długości krótszego obiektu

 

W przypadku działań między macierzą a wektorem wykonywane są działania na poszczególnych elementach macierzy i wektora przy czym macierz zostaje zamieniona najpierw na ciąg (standardowo przez sklejenie kolumn jedna za drugą). Jeżeli wektor jest dłuższy od tego ciągu zostanie użyta do działań tylko jego część i pojawi się komunikat ostrzegawczy. Jeżeli wektor jest krótszy zostanie wielokrotnie powtórzony, tak by jego długość była równa liczbie elementów w macierzy. Jeżeli nie jest to możliwe (wielokrotność wektora jest dłuższa niż liczba elementów macierzy), działanie zostanie wykonane, ale pojawi się komunikat ostrzegawczy.

W podobny sposób wykonywane są działania między dwoma macierzami, ale muszą one mieć te same wymiary.

> mat1=matrix(1:6,2,3)
> mat1
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> mat2=matrix(6:1,2,3)
> mat2
     [,1] [,2] [,3]
[1,]    6    4    2
[2,]    5    3    1
> mat1^mat2
     [,1] [,2] [,3]
[1,]    1   81   25
[2,]   32   64    6
> mat3=matrix(6:1,3,2)
> mat3
     [,1] [,2]
[1,]    6    3
[2,]    5    2
[2,]    4    1
> mat1^mat3
Błąd w poleceniu 'mat1^mat3':niezgodne tablice

 

Funkcje matematyczne działają na macierzach tak samo, jak na wektorach. Wykonywane są na każdym elemencie macierzy osobno.

> mat=matrix(1:6,2,3)
> mat
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> log(mat)
          [,1]     [,2]     [,3]
[1,] 0.0000000 1.098612 1.609438
[2,] 0.6931472 1.386294 1.791759
> sin(mat)
          [,1]       [,2]       [,3]
[1,] 0.8414710  0.1411200 -0.9589243
[2,] 0.9092974 -0.7568025 -0.2794155

 

Większość funkcji statystycznych (min(), max(),sum(), mean(), sd() i inne) działa na macierzach tak, jak na ciągach utworzonych z wyrazów macierzy. Wyjątkiem jest funkcja var(), która tworzy macierz kowariancji dla wektorów utworzonych z poszczególnych kolumn macierzy. Poszczególne elementy tej macierzy wyliczane są ze wzoru:

gdzie  jest L-tym elementem w i-tej kolumnie, jest średnią z elementów i-tej kolumny. Analogicznie dla kolumny j-tej. Na przekątnej tej tabeli lokują się nieobciążone wariancje wyliczone dla kolejnych kolumn macierzy, natomiast pozostałe elementy to kowariancje.

> mat=matrix(1:6,2,3)
> mat
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> max(mat)
[1] 6
> mean(mat)
[1] 3.5
> sd(mat)
[1] 1.870829
> var(mat)
     [,1] [,2] [,3]
[1,]  0.5  0.5  0.5
[2,]  0.5  0.5  0.5
[3,]  0.5  0.5  0.5
> mat1=matrix(1:6,3,2)
> mat1
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[2,]    3    6
> var(mat1)
     [,1] [,2]
[1,]    1    1
[2,]    1    1

 

Dość częstą czynnością jest wyliczanie różnych podsumowań związanych z macierzami. Są to różne obliczenia wykonywane osobno na każdym wierszu lub kolumnie. Do wykonywania podobnych obliczeń służy funkcja apply(). Jej składnia wygląda następująco:

apply(nazwa macierzy, liczba 1 lub 2, funkcja)
Wpisanie 1 w drugiej pozycji powoduje, że funkcja wykonywana będzie na wierszach. Wpisanie 2 w tym miejscu oznacza wykonywanie funkcji w kolumnach.

> mat=matrix(1:9,3,3)
> mat
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> apply(mat, 1, sum)
[1] 12 15 18
> apply(mat, 2, sum)
[1] 6 15 24
> apply(mat, 2, function(x) x-mean(x)) #Od wartości odejmij średnią z kolumny
     [,1] [,2] [,3]
[1,]   -1   -1   -1
[2,]    0    0    0
[3,]    1    1    1
> apply(mat, 1, function(x) x-mean(x)) #Od wartości odejmij średnią z wiersza
     [,1] [,2] [,3]
[1,]   -3   -3   -3
[2,]    0    0    0
[3,]    3    3    3
> # Działanie wykonane dobrze, tylko wyniki zapisane kolumnami, nie wierszami.

 

Poniższy przykład pokazuje działanie funkcji sort(), która porządkuje osobno wiersze albo kolumny.

> mat=cbind(c(1,3,2,0), c(5,7,6,8), c(4,3,6,5))
> mat
     [,1] [,2] [,3]
[1,]    1    5    4
[2,]    3    7    3
[3,]    2    6    6
[4,]    0    8    5
> apply(mat, 2, sort)
     [,1] [,2] [,3]
[1,]    0    5    3
[2,]    1    6    4
[3,]    2    7    5
[4,]    3    8    6
> apply(mat, 1, sort)
     [,1] [,2] [,3] [,4]
[1,]    1    3    2    0
[2,]    4    3    6    5
[3,]    5    7    6    8

 

Najczęściej jednak istnieją powody by zsumować wyrazy w wierszach macierzy lub/i w jej komumnach. Można to robić za pomocą funkcji apply() z funkcją wewnetrznąsum(), ale to samo zrobią funkcje rowSums(), colSums() oraz addmargins().

> mat=cbind(c(1,3,2,0), c(5,7,6,8), c(4,3,6,5))
> mat
     [,1] [,2] [,3]
[1,]    1    5    4
[2,]    3    7    3
[3,]    2    6    6
[4,]    0    8    5
> rowSums(mat))
[1] 10 13 14 13
> colSums(mat)
[1] 6 26 18
> addmargins(mat)
            Sum
1  5  4  10
3  7  3  13
2  6  6  14
0  8  5  13
Sum 6 26 18  50

 

Na koniec pokażemy, jak znajdywać wartości ekstremalne w macierzy i określić, na przecięciu którego wiersza i kolumny one znajdują się.

> ciag=c(4.1, 3.4, 2.6, 2.8, 5.1, 4.0, 5.9, 2.5, 5.1, 3.1, 1.8, 2.4, 5.9, 3.2, 4.3, 2.7)
> macierz=matrix(ciag,4,4)
> macierz
    [,1] [,2] [,3] [,4]
[1,]  4.1  5.1  5.1  5.9
[2,]  3.4  4.0  3.1  3.2
[3,]  2.6  5.9  1.8  4.3
[4,]  2.8  2.5  2.4  2.7
> max(macierz)
[1] 5.9
> which.max(macierz)
[1] 7
> wiersz = which.max(macierz) - 1) %% nrow(macierz) + 1
> kolumna = (which.max(macierz) - 1) %/% nrow(macierz) + 1
> wiersz
[1] 3
> kolumna
[1] 2
> min(macierz)
[1] 1.8
> which.min(macierz)
[1] 11
> wiersz = (which.min(macierz) - 1) %% nrow(macierz) + 1
> kolumna = (which.min(macierz) - 1) %/% nrow(macierz) + 1
> wiersz
[1] 3
> kolumna
[1] 3

 

Funkcje which.max(), which.min() pokazują miejsce pierwszego ekstremum w ciągu liczb, w którym ustawione są kolumny macierzy jedna za drugą. Zamiana tego wyniku na numer kolumny i wiersza wymaga wykonania odpowiednich działań arytmetycznych. Działanie a %% b wylicza resztę z dzielenia a przez b. By zamiast 0 otrzymać liczbę równą liczbie wierszy macierzy, zastosowano wyliczanie reszty z dzielenia od liczby o 1 mniejszej i dodawanie 1 do wyniku. Działanie %/% pokazuje ile razy b mieści się w a. Aby uzyskać właściwy wynik, również zastosowano odejmowanie 1 od dzielnej i dodawanie 1 do wyniku.

Wyznaczenie liczby wartości ekstremalnych można uzyskać za pomocą następujących działań:

> ciag=c(4.1, 3.4, 2.6, 2.8, 5.1, 4.0, 5.9, 2.5, 5.1, 3.1, 1.8, 2.4, 5.9, 3.2, 4.3, 2.7)
> macierz=matrix(ciag,4,4)
> macierz
    [,1] [,2] [,3] [,4]
[1,]  4.1  5.1  5.1  5.9
[2,]  3.4  4.0  3.1  3.2
[3,]  2.6  5.9  1.8  4.3
[4,]  2.8  2.5  2.4  2.7
> macierz[macierz==max(macierz)]
[1] 5.9 5.9
> length(macierz[macierz==max(macierz)])
[1] 2
> macierz[macierz==min(macierz)]
[1] 1.8
> length(macierz[macierz==min(macierz)])
[1] 1

 

Gdy ekstremów funkcji jest więcej niż jeden, aby poznać ich położenie należy użyć funkcji which(ciąg logiczny) zamiast funkcji which.min() albo which.max().

> ciag=c(4.1, 3.4, 2.6, 2.8, 5.1, 4.0, 5.9, 2.5, 5.1, 3.1, 1.8, 2.4, 5.9, 3.2, 4.3, 2.7)
> macierz=matrix(ciag,4,4)
> macierz
    [,1] [,2] [,3] [,4]
[1,]  4.1  5.1  5.1  5.9
[2,]  3.4  4.0  3.1  3.2
[3,]  2.6  5.9  1.8  4.3
[4,]  2.8  2.5  2.4  2.7
> macierz==max(macierz)
[1]      [,1]  [,2]  [,3]  [,4]
[1,] FALSE FALSE FALSE  TRUE
[2,] FALSE FALSE FALSE FALSE
[3,] FALSE  TRUE FALSE FALSE
[4,] FALSE FALSE FALSE FALSE
> which(macierz==max(macierz))
[1] 7 13
> wiersze=(which(macierz==max(macierz)) - 1) %% nrow(macierz) + 1
> wiersze
[1] 3 1
> kolumny=(which(macierz==max(macierz))-1) %/% nrow(macierz) + 1
> kolumny
[1] 2 4

 

Rachunek macierzowy

Rachunek macierzowy tylko pozornie nie jest potrzebny biologom. Na 100 prac biologicznych jedna stosuje macierze do opisu sposobu opracowania danych, do zapisania formuł, jakimi autor posługuje się wyliczając np. strukturę wiekową banku nasion gromadzących się w glebie leśnej, kondycję komórek nowotworowych, których zewnętrzne warstwy niszczone są lekiem itp. Są istotne w modelowaniu ekologicznych, teorii sztucznych inteligencji, metodach numerycznych oraz w statystyce, choć tu gotowe procedury skrzętnie ukrywają stosowanie rachunku macierzowego. Pewne jego elementy powinien jednak biolog znać, zwłaszcza, że żmudne obliczenia wykonywać będzie R, a nie on. Dodatkowym bodźcem do uzyskania umiejętności posługiwania się rachunkiem macierzowym, jest coraz powszechniejsze pojawianie się w pracach biologicznych specjalnych wykresów zwanych biplotami, w których pokazuje się rozrzut danych wielowymiarowych w postaci punktów i poszczególnych zmiennych w postaci wektorów ze strzałkami. Ich zrozumienie i wykonanie wymaga poznania podanych niżej definicji.

Rachunek macierzowy dotyczy tylko macierzy, w której komórkach są liczby. Jeżeli macierz A ma L wierszy i K kolumn, macierz B ma K wierszy i N kolumn to możemy te macierze pomnożyć. Macierz C=A·B będzie mieć L wierszy i N kolumn. Elementem tej macierzy w i-tym wierszu i j-tej kolumnie jest liczba Ci,j równa:

gdzie Ai,k jest elementem macierzy A z i-tego wiersza i k-tej kolumny a Bk,j jest elementem macierzy B i k-tego wiersza i j-tej kolumny. Taki iloczyn nie musi być przemienny. W R iloczyn macierzy wykonuje się za pomocą funkcji crossprod() albo za pomocą operatora “%*%”.

> A=matrix(1:10,2,5)
> A
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
> B=matrix(1:15,5,3)
> B
     [,1] [,2] [,3]
[1,]    1    6   11
[2,]    2    7   12
[3,]    3    8   13
[4,]    4    9   14
[5,]    5   10   15
> A%*%B
     [,1] [,2] [,3]
[1,]   95  220  345
[2,]  110  260  410
> B%*%A
Error in B %*% A : non-conformable arguments

 

Prostym działaniem wykonywanym na macierzy jest jej transpozycja. Polega ona na zamianie macierzy [Ai,j] na macierz [Aj,i], czyli takim zapisaniem elementów macierzy aby jej kolumny stały się wierszami a wiersze kolumnami. W R taką operacje można wykonać za pomocą funkcji t(). Operacja ta działa także na wektorach, przy czym okazuje się, że pojedynczy wektor po transpozycji jest traktowany tak, jak macierz o n wierszach i 1 kolumnie.

> A=matrix(1:15,5,3)
> A
     [,1] [,2] [,3]
[1,]    1    6   11
[2,]    2    7   12
[3,]    3    8   13
[4,]    4    9   14
[5,]    5   10   15
> t(A)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
> B=c(1,5,2,4,3)
> t(B)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    2    4    3

 

Macierze o takiej samej liczbie wierszy i kolumn można mnożyć używając operatora “*”, co opisano w poprzednim podrozdziale. Wynikiem takiego mnożenia nie jest jednak iloczyn macierzy, ale macierz złożona z iloczynów odpowiadających sobie wyrazów.

Macierze kwadratowe w biologii pojawiają się wszędzie tam, gdy sytuacja wymaga wyliczania n pierwiastków układu n równań liniowych. Taki układ równań liniowych zapisuje się często w postaci Ax=B, gdzie A jest macierzą liczbową złożoną z n wierszy i n kolumn, x jest wektorem niewiadomych (x1,…,xn), B jest wektorem liczbowych (B1,…,Bn). Liczby w macierzy A i wektorze B są dane. Pierwiastki te istnieją i są jednoznacznie wyznaczone, gdy wyznacznik macierzy A jest różny od 0. W szkole wyliczany był wyznacznik macierzy o 2 wierszach i 2 kolumnach. Istnieje uogólnienie tego pojęcia dla macierzy kwadratowych o n wierszach i n kolumnach. W R wyliczamy go za pomocą funkcji det().

> A
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> det(A)
[1] 0
> A[1,1]=-1
> A[3,3]=-3
> A
     [,1] [,2] [,3]
[1,]   -1    4    7
[2,]    2    5    8
[3,]    3    6   -3
> det(A)
[1] 162

 

Dla macierzy, która ma wyznacznik różny od 0 istnieje macierz odwrotna. Macierz odwrotna do macierzy A (oznaczana A-1) spełnia warunek: A*A-1=I, gdzie I jest macierzą, która wszędzie ma same zera, a na przekątnej jedynki. Do wyznaczania macierzy odwrotnej służy funkcja solve().

> A
     [,1] [,2] [,3]
[1,]   -1    4    7
[2,]    2    5    8
[3,]    3    6   -3
> odwA=solve(A)
> odwA
           [,1]        [,2]        [,3]
[1,]-0.38888889  0.33333333 -0.01851852
[2,] 0.18518519 -0.11111111  0.13580247
[3,]-0.01851852  0.11111111 -0.08024691
> A%*%odwA
             [,1]          [,2]          [,3]
[1,] 1.000000e+00  5.551115e-17 -2.775558e-17
[2,] 5.551115e-17  1.000000e+00  0.000000e+00
[3,] 3.816392e-17  5.551115e-17  1.000000e+00
> C=matrix(1:9,3,3)
> det(C)
[1] 0
> solve(C)
Error in solve.default(C) :
Lapack routine dgesv: system is exactly singular: U[3,3] = 0

 

Rozwiązanie układu równań postaci:
-1x1 + 4x2 + 7x3 = -7
2x1 + 5x2 + 8x3 = 6
3x1 + 6x2 – 3x3 = -9
wymaga następujących operacji:

> A=matrixei(1:9, 3, 3); A[1,1]=-1; A[3,3]=-3
> B=c(-7, 6, -9)
> solve(A)%*%B
          [,1]
[1,]  4.888889
[2,] -3.185185
[3,]  1.518519
> # albo:
> solve(A,B)
[1] 4.888889 -3.185185 1.518519

 

Pierwiastki pokazanego wcześniej układu równań są równe: x1 = 4.888889, x2 = -3.185185, x3 = 1.518519.

Wykonując pomiary liczbowe k zmiennych dla wielu obiektów operujemy macierzą złożona z k kolumn i dane można traktować jako elementy przestrzeni k-wymiarowej. Tworzą one macierz o k-kolumnach i przeważnie (ale nie zawsze) większej liczbie wierszy (np. n). Większość operacji związanych z rachunkiem macierzowym dotyczy właśnie operacji matematycznych na takich macierzach. Dotyczy to także zależności zarówno statystycznej jak i liniowej poszczególnych zmiennych od siebie, co sprowadza się do analizy zależności poszczególnych kolumn macierzy danych od siebie. Na początek omówiona zostanie liniowa zależność.

Wektor liczb x jest liniowo niezależny od wektorów y1, y2…,yk jeżeli nie istnieją takie liczby (a1,…,ak), że x=a1y1+a2y2+…+akyk. Za symbolami x, y1, y2…,yk kryją się pewne ciągi n-elementowe, zatem mówimy o ciągu n liczb liniowo niezależnym od wierszy macierzy y=[yi,j]i=1..k, j=1..n. Liniową zależność można przedstawić jako istnienie jednokolumnowej macierzy α, że x=y*α. Natomiast liniowa niezależność oznacza, że dla dowolnych macierzy jednokolumnowych α zachodzi x≠y*α. Zysk z zapisu macierzy i wektorów w postaci jednoliterowych symboli jest duży. Strata polega na tym, że wymiary macierzy i liczba elementów w wektorze nie są widoczne – należy je domyślnie kontrolować.

Liniowa niezależność jest związana ściśle z wymiarem przestrzeni, w której można umieścić dane. k liniowo niezależnych wektorów złożonych z n liczb może istnieć tylko wtedy gdy k≤n. Dla k liniowo niezależnych wektorów n-wymiarowych tworzących wiersze w macierzy A, ogół wektorów postaci A*α tworzy przestrzeń kartezjańską k-wymiarową. Jeżeli n>k to kolumny tej macierzy muszą być od siebie zależne, a dokładnie to istnieje k-kolumn liniowo niezależnych, a pozostałe n-k można wyliczyć jako ich liniową kombinację. Z każdą macierzą związany jest wymiar przestrzeni liniowej, w jakiej można umieścić n-elementowe kolumny tej macierzy. Nazywany jest on rzędem macierzy (ang. rank of matrix).

Wyliczanie rzędu dużych macierzy jest dość kłopotliwe. Po prostu nie zawsze widoczna jest liniowa zależność pewnych ciągów od pozostałych. Komputer stosuje do tego celu kilka algorytmów, ale jego obliczenia obarczone są błędem wynikającym z wykonywania obliczeń z pewną dokładnością. Tymczasem definicja rzędu nie uwzględnia zjawiska prawie liniowej zależności, to znaczy że x≈A*α z dokładnością do 0.00000000000001. Jeżeli przyjmiemy, że taka prawie liniowa zależność jest liniową zależnością bo uniemożliwia wykonywanie pewnych operacji macierzowych za pomocą komputera – to możemy programem R posługiwać się przy wyliczaniu rzędu macierzy.

Rząd macierzy wyliczamy za pomocą funkcji rankMatrix(), która znajduje się w bibliotece Matrix, na ogół ładowanej przy instalowaniu R. Należy ją jednak wywołać w konsoli by korzystać z funkcji w niej zawartych.

> A=matrix(1:9,3,3)
> A
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> library(Matrix)
> rankMatrix(A)
[1] 2
attr(,"method")
[1] "tolNorm2"
attr(,"useGrad")
[1] FALSE
attr(,"tol")
[1] 6.661338e-16
> rzadA=rankMatrix(A)[1]
> rzadA
[1] 2

 

Można zauważyć, że w macierzy A ostatni rząd (3,6,9) jest równy 2⋅(2,5,8)-1⋅(1,4,7), czyli kombinacji liniowej rzędów drugiego i pierwszego. Natomiast wektory (2,5,8) i (1,4,7) są liniowo niezależne. Wszystkie wektory postaci α⋅(2,5,8)+β⋅(1,4,7) tworzą płaszczyznę w przestrzeni trójwymiarowej, czyli przestrzeń dwuwymiarową. Stąd rząd macierzy A jest rzeczywiście równy 2.

Wynikiem funkcji rankMatrix() jest złożony obiekt – ciąg jednoelementowy z wyjaśnieniami. Ponieważ często do obliczeń potrzebny jest tylko rząd macierzy należy go wywołać jako rankMatrix( )[1].

Statystyczna zależność k zmiennych od siebie najczęściej liczona jest względem regresji liniowej y=a1x1+a2x2+…+akxk+b, co jest pewną hiperpłaszczyzną w przestrzeni k-wymiarowej. W przypadku liniowej zależności zmiennych x1, x2, …, xk od siebie ta hiperpłaszczyzna ma mniejszy wymiar i nie jest jednoznacznie określona. Dość często generuje to błąd w programach statystycznych. Stąd istnieje w biologii potrzeba wyliczania rzędu macierzy, jaką tworzą dane

Wektory i wartości własne (ang.: eingenvalues and eigenvectors) są integralną częścią pewnego sposobu opracowania danych zwanym analizą składowych głównych (principal component analysis PCA). Pojęcia te odgrywają też dużą rolę w fizyce (analizie drgań, fizyce kwantowej itp.) i być może są lub będą liczone w pewnych pracach biofizycznych. Postaram się zatem wyjaśnić, co one oznaczają.

Mówimy, że macierz A o n-wierszach i n kolumnach ma wartość własną λ (liczbę) i wektor własny x o n wyrazach, jeżeli Ax=λx. Po lewej stronie mnożymy macierze n×n i n×1 (tak traktowany przez R jest wektor), czego wynikiem jest jakiś wektor n-elementowy. Po prawej stronie mnożymy przez liczbę λ wektor x=(x1,x2,…,xn) co jest równe wektorowi (λx1,λx2,…,λxn). Do wyznaczania wektorów i wartości własnych macierzy służy w R funkcja eigen().

> A=matrix(1:9,3,3); A[1,1]=-1; A[3,3]=-3
> eigen(A)
$values
[1] 10.942898 -8.119652 -1.823246
#
$vectors
[,1]       [,2]       [,3] [1,] -0.5033257 -0.5305492 -0.8965518
[2,] -0.7491261 -0.3808798  0.4216953
[3,] -0.4306661  0.7572636 -0.1355284
#
> lambda1=eigen(A)[[1]][1] > lambda2=eigen(A)[[1]][2] > lambda3=eigen(A)[[1]][3] > wek1=eigen(A)[[2]][,1] > wek2=eigen(A)[[2]][,2] > wek3=eigen(A)[[2]][,3] > as.vector(A%*%wek1)
[1] -5.507842 -8.197611 -4.712735
> lambda1%*%wek1
[1] -5.507842 -8.197611 -4.712735
> as.vector(A%*%(2.7*wek2))
[1]  11.631263  8.350051 -16.601536
> lambda2%*%(2.7*wek2)
[1]  11.631263  8.350051 -16.601536
> A%*%wek3-lambda3%*%wek3
[1] [1,]  2.220446e-16
[2,] -1.110223e-16
[3,] -2.498002e-16

 

Pokazywane przez R współrzędne wektorów własnych są przykładowe. Łatwo bowiem sprawdzić, że jeżeli w=(w1,w2,…,wn) jest wektorem własnym o wartości własnej równej λ to dla dowolnej liczby α również wektor u=αw=(αw1,αw2,…,αwn) jest wektorem własnym o tej samej wartości własnej. R wylicza te wektory własne, które znajdują się na sferze jednostkowej (czyli suma kwadratów ich współrzędnych jest równa 1). Pomnożenie ich współrzędnych przez dowolną stałą daje także wektor własny.

Kolejną rzeczą stosowana przy analizie danych jest wyliczanie tzw. wartości osobliwych macierzy i tworzenie jej rozkładu SVD (rozkładu według wartości osobliwych – Singular Value Decomposition). Dla danej macierzy A (nie koniecznie kwadratowej, o n wierszach i m kolumnach) rzędu r (tzn., że co najwyżej r rzędów w tej macierzy jest niezależnych) należy znaleźć takie macierze U (o n wierszach i r kolumnach) i V (o m wierszach i r kolumnach) oraz wartości liczbowe (tzw. wartości osobliwe) σ1, σ2, …,σmin(n,m), aby:

  • t(U)*U = Ir
  • V*t(V) = Ir
  • S = macierz [si,j]i=1,…,n, j=1,…,m spełniała warunek si,ii dla i=1,2,…,min(n,m) oraz si,j=0 gdy i≠j
  • U*S*V-1=A

gdzie t(U), t(V) oznaczają transpozycje macierzy U i V, Ir jest macierzą kwadratową r×r złożoną z samych zer i jedynek występujących tylko na jednej przekątnej (z lewego górnego rogu do prawego dolnego). Jest to macierz jednostkowa r-wymiarowa. Macierze o własnościach t(U)*U = Ir i V*t(V) = Ir nazywamy ortonormalnymi. Gdy któraś z macierzy U lub V jest kwadratowa, to jej transpozycja jest jednocześnie macierzą odwrotną. Wtedy taka macierz nazywana jest ortogonalną.

Biologom takie coś wydaje się kompletnie bez sensu. Dopiero przy tworzeniu wykresów typu biplot pojawia się sensowność wyliczania rozkładu svd danej macierzy, najczęściej wielokolumnowej macierzy danych. Pozwala on bowiem zamienić wielokolumnową macierz danych na macierz dwukolumnową, której zobrazowanie pozwala na wyciąganie wniosków o wzajemnych zależnościach między zmiennymi.

W R rozkład SVD macierzy uzyskujemy za pomocą funkcji svd().

> A=matrix(1:9, 3, 3); A[1,1]=-1; A[3,3]=-3
> svd(A)
$d
[1] 12.472399 7.371181 1.762089

$u
[,1]        [,2]       [,3]
[1,] 0.63433242  0.17395674 -0.7532340
[2,] 0.76771998 -0.02742333  0.6401984
[3,] 0.09071064 -0.98437138 -0.1509456

$v
[,1]       [,2]       [,3]
[1,] 0.09406686 -0.4316700  0.8971134
[2,] 0.55484061 -0.7254629 -0.4072536
[3,] 0.82662163  0.5360640  0.1712660

 

Funkcja svd() umieszcza wartości w liście, której pierwszym elementem jest wektor wartości osobliwych, drugim lewostronna macierz U, a prawym prawostronna macierz V. Można sprawdzić, że są spełnione wszystkie warunki, które powinien spełniać rozkład SVD.

> A=matrix(1:9, 3, 3); A[1,1]=-1; A[3,3]=-3
> svd(A)[[2]]->U
> svd(A)[[3]]->V
> S=matrix(rep(0,9),3,3)
> S[1,1]=svd(A)[[1]][1]
> S[2,2]=svd(A)[[1]][2]
> S[3,3]=svd(A)[[1]][3]
> U%*%t(U)
              [,1]          [,2]          [,3]
[1,]  1.000000e+00 -1.698403e-16  2.456260e-16
[2,] -1.698403e-16  1.000000e+00 -2.144213e-16
[3,]  2.456260e-16 -2.144213e-16  1.000000e+00
> V%*%t(V)
              [,1]          [,2]          [,3]
[1,]  1.000000e+00 -1.498910e-17 -7.337338e-17
[2,] -1.498910e-17  1.000000e+00 -1.594929e-16
[3,] -7.337338e-17 -1.594929e-16  1.000000e+00
> U%*%S%*%t(V)
[,1] [,2] [,3]
[1,]  -1    4    7
[2,]   2    5    8
[3,]   3    6   -3

 

Tags:
Spis treści