--- title: "Zaawansowane typy danych.ipynb" author: "Bartosz Maćkiewicz" subtitle: Statystyka I z R output: html_document: default pdf_document: default --- ## Zaawansowane typy danych W tej części kursu będziemy omawiać bardziej zaawansowane typy danych, z którymi możemy pracować w R. ### Dygresja: `dolna_granica:górna_granica` Na początek nauczymy się tworzenia wektorów liczb całkowitych (`integer`) za pomocą konstrukcji `dolna granica:górna granica`. Jest to bardzo często wykorzystywany sposób, który pojawiać będzie się przez cały kurs. ```{r} dwadziescia_liczb <- 1:20 # Tworzymy wektor typu integer z liczbami od 1 do 20 dwadziescia_liczb # sprawdzamy czy rzeczywiście się utworzył class(dwadziescia_liczb) # sprawdzamy jego typ ``` Jeżeli jaki pierwszą podamy mniejszą liczbę, to R z takim wypadkiem sobie poradzi i również utworzy ciąg liczb całkowitych. ```{r} 5:1 ``` Jeżeli interesują nas bardziej wyrafinowane sekwencje liczb, to powinniśmy zainteresować się funkcja `seq`. Poniżej znajduje się przykład polecenia, tworzącego sekwencję liczb całkowitych od 5 do 56, w ktorej każda kolejna liczba jest większa od poprzedniej o 3. Więcej o tej funkcji można znaleźć w dokumentacji (`?seq`) ```{r} seq(from = 5, to = 55, by = 3) ``` ## Macierze Utwórzmy też macierz o wymiarach 4x5. Kolejne liczby z wektora `dwadziescia_liczb` wypełniają po kolei kolumny naszej macierzy. Zrobimy to za pomocą funkcji `matrix`. ```{r eval = F} matrix(dane, wiesze, kolumny) ``` - `dane` - wartości, którymi chcemy wypełnić macierz - `wiesze` - liczba wierszy - `kolumny` - liczba kolumn Warto w tym miejscu zwrócić uwagę na dwa fakty. 1. R domyślnie wypełnia macierze kolumnami 2. Jeżeli jakaś funkcja przyjmuje jako argumenty wymiary jakiejś dwuwymiarowej struktury danych, to najpierw podaje się liczbę wierszy a dopiero potem liczbę kolumn. Oto mnemotechniczna rymowanka, która pozwala zapamiętać to zachowanie: *wiersze pierwsze*. ```{r} macierz <- matrix(dwadziescia_liczb, 4,5) macierz ``` Za pomocą argumentu `byrow` możemy jednak wypełniać macierz wierszami. ```{r} macierz_wiersze <- matrix(dwadziescia_liczb, 4,5, byrow = TRUE) macierz_wiersze ``` Do macierzy możemy dodawać nowe wiersze i kolumny za pomocą funkcji `cbind` i `rbind`. ```{r} print(cbind(macierz_wiersze, c(1000,2000,3000,400))) # analogicznie rbind ``` ```{r} print(rbind(macierz_wiersze, macierz_wiersze)) # możemy nawet "złączyć" dwie macierze w ten sam sposób ``` Na macierzach podobnie jak na wektorach możemy wykonywać operacje element-po-elemencie, na przykład mnożenie. ```{r} macierz * macierz_wiersze # mnożenie R-owe, "element-po-elemencie" ``` Możemy również wykonywać operacje algebraiczne na macierzach. ```{r} a <- matrix(c(2,4,6,8,10,12,14,18), 2,4) a ``` ```{r} b <- matrix(c(9,8,7,6,5,4,3,2), 4,2) b ``` ```{r} a %*% b # iloczyn macierzy ``` Inne przydatne podstawowe operacje: - `t` - transpozycja ```{r} # inny sposób tworzenia macierzy za pomocą funkcji cbind (*column bind*) macierz_2 <- cbind(30:40, 25:35, 130:140) t(macierz_2) # Transpozycja ``` - `rowSums`, `colSums`, `rowMeans`, `colMeans` - sumy/średnie kolumnami/wierszami ```{r} rowMeans(macierz_2) # analogiczne colMeans colSums(macierz_2) # analogicznie rowSums ``` O wymiarach macierzy możemy się dowiedzieć za pomocą funkcji `dim`, `ncol`, `nrow` ```{r} dim(macierz_2) # wymiary ncol(macierz_2) # liczba kolumn nrow(macierz_2) # liczba wierszy ``` Dla naszych celów ta wiedza powinna wystarczyć, statystycy z socjologii prosili jednak o podstawy algebry w R. Polecam więc zajrzenie w stosownym czasie do np. [Algebra w R](https://www.r-bloggers.com/quick-review-of-matrix-algebra-in-r/) (polecam również samą stronę!) ## Listy Listy w przeciwieństwie do wektorów przechowują sekwencje wartości różnych typów. Możemy w niej przechowywać wektory różnych typów o różnej długości a nawet inne listy. W tym sensie są podobne do list z niektórych innych języków programowania. Listy tworzymy za pomocą funkcji `list`. ```{r} lista <- list(c(1,2,3,4,5), # pierwszy element: wektor typu `integer` c('Adam', 'Marysia', 'Zosia', 'Tosia'), # drugi element: wektor typu `character` TRUE, # trzeci element: wektor typu `logical` TRUE, # czwarty element: wektor typu `logical` list( # piąty element: lista c(-1,-2,-3) # pierwszy element: wektor typu `numeric` ) ) lista ``` Elementom listy możemy nadawać nazwy. Dlatego w niektórych sytuacjach możemy traktować je jak słowniki z innych języków programowania, przechowujące pary klucz-wartość. Nazwane listy również tworzymy przy pomocy funkcji `list`. ```{r} lista_nazwana <- list(liczby_od_jeden_do_piec = c(1,2,3,4,5), imiona = c('Adam', 'Marysia', 'Zosia', 'Tosia'), czy_r_jest_fajny = TRUE, czy_zajecia_sa_fajne = TRUE, lista_zagniezdzona = list(c(-1,-2,-3))) lista_nazwana ``` Do list wrócimy jeszcze kiedy będziemy mówić o indeksowaniu. ## Ramki danych (*data frame*) Ramki danych (*data frame*) są typem danych, z którym w praktyce będziemy pracować najczęściej. O ramkach danych można myśleć jako np. o tabelach Excela, w której każdy wiersz reprezentuje jedną obserwację. Tworzenie ramek danych jest dość podobne do tworzenia list. To, co w listach było nazwami elementow, w przypadku ramek danych będzie nazwami kolumn. Poniżej znajduje sie kilka przydatnych sposobów tworzenia ramek danych. Na razie pomijamy najczęściej wykorzystywany w praktyce sposób. Z reguły bowiem ramki danych będziemy tworzyć wczytując dane z pliku. Tym jednak zajmiemy się później. Podstawowy sposób stworzenia ramki danych wygląda tak: ```{r} x <- c('Kasia', 'Zosia', 'Marysia', 'Tosia', 'Zbyszek') y <- factor(c('F', 'F', 'F', 'F', 'M'), levels = c('F','M')) z <- c(2, 4, 5, 8, 2) # ramki danych tworzy się w zasadzie tak samo jak listy dane <- data.frame(imie = x, plec = y, liczba_jabluszek = z ) dane ``` Jeśli mamy listę, której elementy są wektorami równej długości, to możemy przekonwertować ją na ramkę danych. ```{r} lista_nie_ramka <- list(imie = x, plec = y, liczba_jabluszek = z) data.frame(lista_nie_ramka) ``` W ramce danych nie tylko kolumny mogą mieć swoją nazwę. Możemy ustalić, że również każdy wiersz będzie miał nazwę. Uczynimy to przekazując funkcji `data.frame` argument `row.names` w postaci wektora z nazwami. ```{r} data.frame(plec = y, liczba_jabluszek = z, row.names = x) ``` Do postaci ramki danych możemy przekonwertować również macierz. Czasami jest to przydatne. Służy do tego funkcja `as.data.frame`. ```{r} ramka_z_macierzy <- as.data.frame(macierz) # możemy utworzyć z macierzy ramka_z_macierzy ``` Powiedzieliśmy sobie, że w ramkach danych kolumny oraz wiersze mogą mieć nazwy. Jeśli chodzi o kolumny, to funkcji `colnames` zwraca wektor z nazwami kolumn ramki danych. ```{r} dane colnames(dane) ``` Za pomocą tej samej funkcji możemy zmienić też nazwy. Wystarczy, że nadpiszemy zwrócony przez funkcję `colnames` wektor swoim własnym wektorem, w którym zawrzemy nowe nazwy kolumn. To samo możemy zrobić również z nazwami wierszy, korzystając w funkcji `rownames`. ```{r} ramka_z_macierzy # Zastępujemy domyśle nazwy kolumn (V1, V2, V3...) swoimi własnymi. colnames(ramka_z_macierzy) <- c('Jeden', 'Dwa', 'Trzy', 'Cztery', 'Pięć') ramka_z_macierzy ```