Wektory i macierze dla zaawansowanych
Poznaliśmy już wektory i macierze i podstawowe operacje na nich, pora podnieść nieco poprzeczkę i nauczyć się bardziej zaawansowanych, a przy tym znacznie ciekawszych funkcji.
Kilka pożytecznych funkcji, które najlepiej poznać po prostu sprawdzając, jak działają:
> ceny = c(2.80, 4.60, 2.70, 8.40) > length(ceny) # dlugosc [1] 4 > sum(ceny) # suma [1] 18.5 > mean(ceny) # srednia [1] 4.625 > max(ceny) # chyba nie trzeba tlumaczyc... [1] 8.4 > min(ceny) [1] 2.7 > names(ceny) # sprawdzamy czy elementy w naszym wektorze maja nazwy NULL > # nie maja? no to je dodamy > names(ceny) = c("chleb", "czekolada", "sok", "maslo orzechowe") > ceny chleb czekolada sok maslo orzechowe 2.8 4.6 2.7 8.4 > > ceny["czekolada"] # teraz mozemy dostac sie do elementu po jego nazwie, nie tylko numerze! czekolada 4.6 > 2.8 %in% ceny # sprawdzamy czy wartosc 2.8 jest w wektorze [1] TRUE > "czekolada" %in% names(ceny) # a teraz czy wartosc "czekolada" jest w wektorze nazw wektora ceny [1] TRUE > "makaron" %in% names(ceny) [1] FALSE > ceny[ ceny > 3 ] # wyswietlimy tylko te elementy wektora, ktore sa wieksze od 3 czekolada maslo orzechowe 4.6 8.4
Ostatnie polecenie może na pierwszy rzut oka wyglądać mało intuicyjnie. Wpiszmy najpierw samo ceny > 3 i zobaczmy, co wyjdzie:
> ceny > 3 chleb czekolada sok maslo orzechowe FALSE TRUE FALSE TRUE
No tak, wektor TRUE / FALSE. Z tego wynika, że jeśli wektor wartości logicznych wpiszemy jako indeksy wektora, dostaniemy wektor z elementami odpowiadającymi wartościom TRUE. Na przykład:
> ( wektor = 1:5 ) [1] 1 2 3 4 5 > wektor[ c(TRUE, TRUE, FALSE, FALSE, TRUE) ] [1] 1 2 5
Podobne rzeczy można robić oczywiście z macierzami:
> ( macierz = matrix(1:9, ncol = 3) ) [,1] [,2] [,3] [1,] 1 4 7 [2,] 2 5 8 [3,] 3 6 9 > dim(macierz) # dimensions, czyli wymiary [1] 3 3 > colnames(macierz) = c("a", "b", "c") > rownames(macierz) = c("I", "II", "III") > macierz a b c I 1 4 7 II 2 5 8 III 3 6 9 > macierz["I",] a b c 1 4 7 > macierz["II","c"] [1] 8 > macierz[-1,"c"] # bez pierwszego wiersza, tylko kolumna "c" II III 8 9 > macierz[ macierz %% 2 == 1 ] # wszystkie wartosci, dla ktorych spelnione jest, ze reszta z dzielenia to 2 [1] 1 3 5 7 9 > sum(macierz) [1] 45
Jeśli nie tylko przeczytałeś/aś już wszystkie powyższe polecenia, ale też przepisałeś/aś je u siebie do R-a, przetestowałeś/aś i sądzisz, że rozumiesz już ich działanie, to możemy zanurkować jeszcze głębiej, poznawać kolejne ciekawe funkcje:
> which( c(TRUE, FALSE, TRUE, FALSE, FALSE) ) # na ktorych indeksach jest TRUE [1] 1 3 > which( c(1,2,3) ) # to nie zadziala, musza byc true / false Error in which(c(1, 2, 3)) : argument to 'which' methods/html/is.html">is not logical > which( 1:10 %% 3 == 0 ) # no to zrobmy true / false - sprawdzmy, gdzie sa w wektorze 1:10 liczby podzielne przez 3 [1] 3 6 9 > length( which( 1:100 %% 11 == 0 ) ) # ile jest liczb podzielnych przez 11 od 1 do 100? [1] 9 > wektor = c(4,3,0,5,11,2) > sort(wektor) # zwroc wektor posortowany (oczywiscie zmienna wektor pozostaje nietknieta) [1] 0 2 3 4 5 11 > order(wektor) # zwroc kolejnosc wektora, tj. na jakim miejscu bylyby poszczegolne elementy, gdyby byl posortowany [1] 3 6 2 1 4 5 > wektor[ c(2,4,6,1,3,5) ] # podajemy wektor indeksow - tu podalismy wszystkie, ale w dziwnej kolejnosci, wiec namieszalismy kolejnosc w wektorze [1] 3 5 2 4 0 11 > wektor[ order(wektor) ] # troche na okolo sposob na sortowanie wektora... [1] 0 2 3 4 5 11 > inny_wektor = c("a","b","c","d","e","f") > inny_wektor[ order(wektor) ] # sortujemy inny_wektor wg kolejnosci w wektorze wektor [1] "c" "f" "b" "a" "d" "e" > inny_wektor[ order(wektor) ][ wektor != 4 ] # i wywalamy wartosci z tych pozycji, na ktorych w wektorze wektor mamy liczbe 4 [1] "f" "b" "a" "d" "e"
Jeżeli pojęłaś/pojąłeś dokładnie wszystko, co dzieje się w powyższym fragmencie kodu, jesteś gotowa/y poznać jedną z najpożyteczniejszych funkcji R-a: apply. Jest to funkcja działająca na macierzach, która wykonuje jakąś żądaną przez nas operację na wszystkich wierszach / kolumnach danej macierzy. Przykład użycia:
Pierwszym argumentem jest macierz, na której chcemy coś policzyć. Drugi argument wynosi 1, jeśli chcemy zrobić coś na wierszach, albo 2 jeśli na kolumnach (można zapamiętać w ten sposób, że podając indeksy wierszy i kolumn zawsze pierwsze są wiersze, aczkolwiek można też nie pamiętać i skorzystać z helpa wpisując ?apply). Trzeci mówi, jaką funkcję chcemy zastosować. Wynikiem jest wektor: w pierwszym przypadku, dostaliśmy wektor dwuelementowy, bo operację wykonywaliśmy na wierszach, których było dwa: R zsumował pierwszy wiersz, wyszło mu 9, zsumował drugi, wyszło mu 12; zwrócił więc wektor c(9, 12). W drugim przypadku działaliśmy na kolumnach i dostaliśmy wektor sum kolejnych kolumn.
Oczywiście jest to ledwie garstka funkcji, które są dostępne w R-ze. Ciekawskim polecam poczytanie o innych funkcjach i przetestowanie ich działania, np. sample, rank, rev, diag czy outer, oraz sięgnięcie do rozmaitych zewnętrznych źródeł.