Podstawy wykorzystania języka R Michał Ramsza, Mariusz Kozakiewicz wersja z dn. 2017-10-30 1
Spis treści 1 Wprowadzenie 3 1.1 Język R..................................... 3 1.2 Instalacja.................................... 3 1.3 Środowisko pracy................................ 3 2 Podstawy pracy z językiem R 4 2.1 Praca w konsoli................................. 4 2.2 Pierwszy skrypt................................. 4 3 Podstawowe zadania wejścia / wyjścia 5 3.1 Zapisywanie wykresów............................. 5 3.2 Zapisywanie danych liczbowych........................ 6 3.3 Wczytywanie danych.............................. 6 4 Struktury danych 7 4.1 Wprowdzenie.................................. 7 4.2 Wektory..................................... 7 4.3 List........................................ 12 4.4 Ramki danych.................................. 13 5 Elementy programowania 14 5.1 Bloki kodu.................................... 14 5.2 Wykonania warunkowe............................. 15 5.3 Iterowanie.................................... 16 5.4 Przykład zastosowania............................. 17 5.5 Wprowadzenie do funkcji............................ 18 2
1 Wprowadzenie 1.1 Język R Język programowania R jest przeznaczony do analizy danych. Język ten może być relatywnie prosty na podstawowym poziomie lub relatywnie złożony na poziomie zaawansowanym. Niniejsze materiały są przewidziane dla osób bez uprzedniej znajmości języka R. 1.2 Instalacja W systemie MacOS oraz w systemie MS Windows należy ściągnąć plik instalacyjny ze strony https://www.r-project.org. W przypadku dużych dystrybucji systemów z rodziny Linux wystarczy skorzystać ze standardowych repozytoriów. 1.3 Środowisko pracy W systemach MacOS oraz MS Windows standardowa instalacja języka R instaluje dodatkowo aplikację zawierającą emulator konsoli oraz prosty edytor skryptów. W podstawowym wykorzystaniu jest całkowicie wystarczające środowisko pracy. W systemach z rodziny Linux można pracować bezpośrednio w konsoli oraz wykorzystać dowolny edytor. Istnieje kilka możliwości zastąpienia standardowego edytora skryptu. Jedną z bardziej popularnych możliwoście jest wykorzystanie edytora RStudio dostępnego na stronie https://www.rstudio.com. Innym, bardziej zaawansowanym wyjściem jest wykorzystanie edytora Emacs, dostepnego na stronie https://www.gnu.org/software/emacs/ razem z dodatkowymi pakietami, np. ESS (https://ess.r-project.org) oraz Org (http://orgmode.org). 3
2 Podstawy pracy z językiem R 2.1 Praca w konsoli Podstawową logiką pracy z językiem R jest wykorzystanie pętli REPL (and. read eval print loop). Z punktu widzenie użytkownika polega to na podaniu wyrażenia, które jest nastepnie obliczane (interpretowane) a wynik jest zwracany do użytkownika. Dokładnie taka jest logika pracy w konsoli. Po wpisaniu wyrażenia i wciśnięciu Enter wyrażenie zostaje przesłane do interpretera, obliczone a wynik obliczenia jest wydrukowany w konsoli. Praca w takim reżimie jest oczywiście możliwa ale raczej nieefektywna. Z tego powodu, podstawową metodą pracy w języku R jest pisanie skryptów. 2.2 Pierwszy skrypt Korzystając ze standardowejgo edytora każde wyrażenie można wykonać korzystając ze skrótu Ctrl-R. Pozwoli to na wykonanie wyrażenia w lini w której stoi kursor. Pierwszy skrypt będzie sprawdzał jaki jest katalog roboczy oraz jak ustalić nowy katalog roboczy. 1 ### Zmiana katalogu roboczego 2 getwd () # sprawdzanie katalogu roboczego 3 setwd ("/ Users / michael / Desktop / ksap /") # ustawianie katalogu roboczego Każda funkcja jest wywoływana jako nazwa, po której podawana jest lista argumentów rozdzielonych przecinkami. 4
3 Podstawowe zadania wejścia / wyjścia 3.1 Zapisywanie wykresów Typowe zadanie, które bardzo często jest wykorzystywane to tworzenie i zapisywanie wykresów do plików graficznych, które mogą być później wykorzytywane w zewnętrznych programach. Poniżej podany jest przykład prostego skryptu, który tworzy wektor liczb losowych z rozkładu normalnego a następnie zapisuje go do pliku PNG. 1 ### Tworzenie danych 2 x <- rnorm (10^3, 0, 1) 3 4 ### Tworzenie wykresu i zapisywanie do pliku 5 ### otworzenie pliku na dysku 6 png ( file = " fig1. png ") 7 8 ### tworzenie histogramu 9 hist (x, 10 col =" lightblue ", 11 freq = FALSE, 12 main =" Title ") 13 14 ### dodawanie estymowane funkcji gestosci 15 lines ( density (x), 16 col =" red ", 17 lwd = 1, 18 lty = " dashed ") 19 20 ### konieczne zamkniecie pliku na dysku 21 dev. off () 5
3.2 Zapisywanie danych liczbowych Drugą typową operacją jest zapisywanie danych liczbowych na dysku. Poniższy skrypt pokazuje jak stworzyć prostą ramkę danych (ang. data frame) i zapisać ją w postaci pliku w formacie CSV. 1 ### Zapisywanie danych liczbowych 2 n <- 10^3 # parametr / jak duza proba jest tworzona 3 x <- data. frame ( lp = 1: n, dane = rnorm ( n)) # tworzenie ramki danych z losowymi liczbami 4 write. csv ( file = " dane. csv ", x) # zapisywanie do pliku CSV w katalogu roboczym 3.3 Wczytywanie danych Trzecią typową operacją jest wczytywanie danych liczbowych. Poniższy skrypt pokazuje jak wczytać zapisany uprzednio plik w formacie CSV. 1 ### Wczytywanie danych 2 dane <- read. csv ( file = "./ dane. csv ") # wczytywanie danych z pliku w katalogu roboczym 3 4 ### Wizualizacja danych 5 hist ( dane $ dane, density = 10, angle = 45) # tworzenie prostego histogramu Zapisywanie i wczytywanie danych w formacie CSV pozwala na wymianę danych np. z programem Excel. 6
4 Struktury danych 4.1 Wprowdzenie W języku R jest wielu tzw. podstawowych typów danych. Z punktu widzenia wykorzystania na poziomie podstawowym najważniejsze dwie struktury danych: wektory i listy, oraz jedna klasa: ramka danych. Kolejne przykłady pokażą jak tworzyć i indeksować wszystkie te struktury danych. 4.2 Wektory 4.2.1 Tworzenie wektorów Wektor jest to uporządkowana ciąg danych, np. (x 1, x 2,..., x n ), gdzie x i są dowolnymi elementami. Wektor może zawierać tylko jeden typ danych. W R każda liczba to jest już wektor. Poniższy przykład pokazuje jak łączyć wektory proste w nieco bardziej skomplikowane. 1 ### Prosty wektor 2 2 3 4 ### Laczenie wektorow 5 c( 2, 5, 8, 20) 6 7 ### Laczenie wektorow 2 8 x <- c( 1,2,3) 9 c( x, x, x) 10 11 ### Laczenie wektorow 3 12 x <- c( 1, 2, 3) 13 y <- c( 7, 8) 14 c( x, y, x, y) 7
4.2.2 Generowanie wektorów Do automatycznego tworzenia bardziej skomplikowanych wektorów można wykorzystać następujące trzy funkcje : seq() rep() Poniższy przykład pokazuje zastosowanie podstawowego operatora :. 1 ### Wykorzystanie operatora : 2 1:5 3 1.13:5 4 5:1 5 6 ### Operator : jest wykonywany przed innymi operatorami 7 1+2: 5 8 1:5-1 9 10 ### Wyjatki 11-1:5 12 1: 2^2 13 14 ### Operator : mozna laczyc z innymi funkcjami 15 1: rbinom ( 1, 10, 0.5) Wykorzystanie funkcji seq() do tworzenie wykresu podanej funkcji. 1 ### Przykladowe wykorzystanie funkcji seq 2 seq ( 0, 1,.1) 3 seq ( 0, 1, length. out = 13) 4 5 ### Wykorzystanie funkcji seq przy tworzeniu wykresu funkcji 6 x <- seq (-pi, pi, length. out = 50) 7 y <- sin (x) 8
8 plot ( x, y, type = "o", 9 pch = 20, 10 col = " blue ") Wykorzystanie funkcji rep() do tworzenie prostego wykresu sezonowego. 1 ### Proste wykorzystanie 2 rep (3, 5) 3 rep ( 1:3, 5) 4 rep ( 1:4, 5) 5 6 ### Wykres sezonowy 7 liczbalat <- 50 8 liczbaokresow <- 4 9 dane <- rnorm ( liczbaokresow * liczbalat ) 10 sez <- c(1, -.5, -1, 0) 11 dane. sez <- dane + sez 12 13 ### Wykres czeregu czasowego 14 plot ( dane.sez, type = "o", 15 pch = 20, 16 col = " blue ") 17 18 ### Wykres sezonowy 19 x <- rep ( 1: liczbaokresow, liczbalat ) 20 plot ( jitter ( x), dane.sez, 21 pch = 20, 22 cex = 1, 23 col = rgb ( 0, 0, 1,.2) ) 24 abline ( v = 1: liczbaokresow +. 5) 4.2.3 Indeksowanie wektorów Wektory można indeksować na trzy sposoby przez podanie pozycji, 9
przez podanie wektora logicznego, przez nazwy (trzeba je nadać). Przykład indeksowania przez podanie pozycji. 1 ### Indeksowanie przez pozycje 2 x <- 5:1 3 x [1] 4 x[c (1,3,5) ] 5 x[c(1, 2, 3)] 6 x [1:3] 7 x [3:5] 8 9 ### Usuwanie elementow wektora 10 x[ -1] 11 x [ -(2:4) ] Przykład indeksowania przez wektor logiczny. 1 ### Wektory logiczne i ich wykorzystanie 2 x <- 5:1 3 ind <- x < 3 4 x[ ind ] 5 6 ### Besposrednie indeksowanie 7 y <- 1: 10 8 y[y >3 & y < 7] 9 10 ### Prosty przyklad indeksowania 11 z <- c( "a", "b", "c") 12 z[c(true, FALSE, TRUE )] Prosty przyklad wykorzystania indeksowania przez wektor logiczny do wyboru elementów szerego czasowego na podstawie warunków logicznych. 1 ### Tworzenie danych 2 dane <- cumsum ( rnorm ( 100) ) 3 t <- 1: length ( dane ) 10
4 v <- mean ( dane ) 5 6 ### Tworzenie indeksu logicznego 7 ind <- dane < v 8 9 ### Wykorzystanie do wyboru elementow 10 plot ( x = t, 11 y = dane, 12 type = "l", 13 cex = 2, 14 col = " black ", 15 pch = 20) 16 points ( t[ ind ], dane [ ind ], 17 col = " red ", 18 pch = 20, 19 cex = 1) 20 points ( t[! ind ], dane [! ind ], 21 col = " blue ", 22 pch = 20, 23 cex = 1) Poniższy przykład pokazuje proste zastosowanie indeksowania przez wykorzystanie nazwy. 1 ### Tworzenie danych i nadawanie nazw 2 x <- 1:3 3 names ( x) <- c(" ala ", " bela ", " cela ") 4 5 ### Wykorzystanie do indeksowania 6 x[" ala "] 7 x[" cela "] 11
4.3 List 4.3.1 Tworzenie listy Lista to lista pozycji z nazwami, która może przechowywać dowolne dane i to jest jej główna przewaga nad wektorem. Poniższy przykład pokazuje jak tworzy się listy oraz jak się je łączy. 1 ### Tworzenie listy 2 dane <- list ( 3 " kraj " = " Polska ", 4 " populacja " = 38000000, 5 "EU" = TRUE ) 6 7 ### Drukowanie listy 8 dane 9 10 ### Laczenie list 11 dane1 <- c( dane, list ( " NATO " = TRUE )) 12 dane1 13 14 ### Pozyskiwanie nazw pozycji 15 names ( dane1 ) 4.3.2 Indeksowanie listy Listy można indeksować na trzy sposoby: poprzez nazwę pozycji oraz na dwa sposoby poprzez podanie pozycji z wykorzystaniem następujących operatorów [], [[]]. 1 ### Tworzenie listy 2 dane <- list ( 3 " kraj " = " Polska ", 4 " populacja " = 30000000, 5 "eu" = TRUE, 6 " nato " = TRUE 7 ) 12
8 9 ### Indeksowanie 1 10 dane $ kraj 11 dane $eu 12 dane $ nato 13 14 ### Indeksowanie 2 15 dane [1] 16 dane [4] 17 18 ### Indeksowanie 3 19 dane [[1]] 20 dane [[4]] 21 22 ### Indeksowanie 4 23 dane [[" kraj "]] 24 dane [[" nato "]] 4.4 Ramki danych 4.4.1 Tworzenie Ramki danych to podstawowa struktura do przechowywania danych. Jest to struktura dwuwymiarowa, która posiada wiersze oraz kolumny. Ramki danych tworzy się przy pomocy funkcji data.frame(). 1 ### Tworzenie 2 dane <- data. frame ( 3 "lp" = 1:5, 4 " value " = rnorm ( 5) 5 ) 6 7 ### Drukowanie ramki danych 8 dane 13
4.4.2 Indeksowanie ramki danych Ramki danych można indeksować tak jak wektory oraz tak jak listy oraz można te metody mieszać. Indekowanie przeprowadza się na obu wymiarach a więc zarówno na wierszach jak i na kolumnach. 1 ### Tworzenie 2 dane <- data. frame ( 3 "lp" = 1:5, 4 " value " = rnorm ( 5), 5 " label " = sample ( letters [1:3], 5, replace = TRUE ) 6 ) 7 8 ### Przyklady indeksowania 9 dane $ value 10 dane [,] 11 dane [," value "] 12 dane [1:3,] 13 ind <- dane $ value < mean ( dane $ value ) 14 dane [ind, ] 15 dane [ind, " value "] 16 17 ### Wybor wierszy o nieparzystych i parzystych wierszy 18 ind <- as. logical ( dane $ lp %% 2) 19 dane [ind,] 20 dane [!ind,] 5 Elementy programowania 5.1 Bloki kodu Blok kodu oznacza się przez nawiasy {}. Blok kodu jest podstawową jednostką kodu. Poniższy przykład pokazuje jak cały fragment kodu może zostać przekazany jako pojedynczy argument. 14
1 ### Wczytanie danych 2 data ( cars ) 3 head ( cars ) 4 5 ### Podstawowy wykres jako oddzielny kod 6 plot ( cars ) 7 abline ( v = mean ( cars $ speed )) 8 abline ( h = mean ( cars $ dist )) 9 10 ### Wykorzystanie bloku 11 with ( cars, 12 { plot ( cars, pch = 20, col = " red ") 13 abline ( v = mean ( speed ), col = " blue ") 14 abline ( h = mean ( dist ), col = " blue ") } 15 ) 5.2 Wykonania warunkowe Wykonanie warunkowe to podstawowa struktura sterująca działaniem programu. Podstawowa konstrukcja wykonania warunkowego jest postaci if(warunek){} else {}. Poniższy przykład pokazuje proste wykorzystanie takiej struktry. 1 ### Prosty przyklad 2 x <- 2 3 if( x > 0 ) { 4 print ( " Zmienna x jest dodatnia.") 5 } 6 7 x <- -1 8 if( x > 0 ) { 9 print ( " Zmienna x jest dodatnia.") 10 } 11 12 ### Przyklad nieco bardziej skomplikowany 13 x <- -1 14 if( x > 0 ){ 15
15 print ( " Zmienna x jest dodatnia ") 16 } else { 17 print ( " Zmienna x nie jest dodatnia ") 18 } 5.3 Iterowanie 5.3.1 Podejście proceduralne Typowym podejściem do iterowania jest podejście proceduralne i w ramach tego podejścia typowe jest wykorzystanie pętli for. Podstawowa pętla for jest postaci for(k in X){}, gdzie X to wektor lub lista. Poniższy przykład pokazuje typowe wykorzystanie takiej konstrukcji. 1 ### Podstawowy przyklad 2 for ( k in 1:10) { 3 print ( k ^2) 4 } 5.3.2 Podejście funkcyjne / wektoryzacja Podejście fukcyjne polega na zastosowaniu funkcji do całości wektora. To podejście w R jest zazwyczaj znacznie szybsze niż podejście wykorzystujące pętle. Poniższy przykład pokazuje typowe zastosowanie wektoryzacji. 1 ### Powyzszy przyklad zwektoryzowany 2 (1:10) ^2 16
5.4 Przykład zastosowania 5.4.1 Tworzenie wielu plików z danymi Poniższy przykład tworzy katalog w katalogu roboczym, i w tym nowy katalogu tworzy 100 plików z przykładowymi danymi. 1 ### Weryfikacja katalogu roboczego 2 getwd () 3 4 ### Tworzenie nowego katalogu 5 datadirname <- " dane " 6 if(! dir. exists ( datadirname )){ 7 dir. create ( path = datadirname ) 8 } 9 10 ### Przechodzenie do nowego katalogu 11 wd <- setwd ( datadirname ) 12 13 ### Tworzenie przykladowy plikow 14 n <- 100 15 fn <- " dane _" 16 for ( alamakota in 1: n){ 17 temp <- data. frame ( " values " = rnorm ( 10) ) 18 write. csv ( file = paste0 ( fn, as. character ( alamakota ), ". csv "), temp 19 } ) 20 21 ### Powracanie do poczatkowego katalogu roboczego 22 setwd ( wd) 5.4.2 Wczytywanie wielu plików z danymi Przykład modelujący sytuację, w kórej dane przychodzą w wielu plikach. 1 ### Przejscie do katalogu zawierajacego dane 17
2 datadir <- "./ dane " 3 wd <- setwd ( datadir ) 4 5 ### Wczytanie wszystkich plikow 6 fs <- list. files ( pattern = ". csv ") 7 data <- c() 8 for ( f in fs){ 9 data <- c( data, read. csv ( file = f)$ values ) 10 } 11 12 ### Powrot to poczatkowego katalogu 13 setwd (wd) 14 15 ### Tworzenie raportu 16 png ( file = " fig1. png ") 17 hist ( data, " Scott ", freq = FALSE, col = " red ", 18 density = 20) 19 dev. off () 5.5 Wprowadzenie do funkcji Funkcje służą do strukturalizacji kodu, tak aby ten sam fragment kodu można było wielokrotnie wykonywać. Podstawowa konstrukcja definiująca funkcję to f <- function(){}. 1 ### Prosty przyklad 2 f1 <- function (){ 3 print ( " hello!") 4 } 5 6 ### Przykladowe wywolanie 7 f1 () 8 9 for ( k in 1:10) { 10 f1 () 11 } 12 18
13 ### Bardziej skomplikowany przyklad 14 f2 <- function ( k){ 15 for ( j in 1:k){ 16 print ( " hello!") 17 } 18 } 19 20 f2 (5) 21 f2 (10) 22 23 f3 <- function ( a, b){ 24 a + b 25 } 26 27 x <- f3( 2, 3) 28 x Funkcje, które przyjmują wartości domyślne. 1 f4 <- function ( a, b = 0){ 2 a + b 3 } 4 5 f4( 2, 4) 6 f4( 2) 7 f4( a = 2, b = 4) 8 f4( b = 4, a = 3) W R można wykorzystać prosty mechanizm przekazywania argumentów. Poniżej podany jest przykład prostej funkcji, która jako argumenty przyjmuje funkcję (w sensie matematycznym) oraz dowolna liczby nazwanych argumentów, które przekazywane są dalej do funkcji plot() pozwalając na dowolne sterowanie stylem wykresu. 1 ### Funkcja pozwalajaca na sterowanie stylem wykresu 2 styleplot <- function ( f, dom, n = 50,...) { 3 x <- seq ( min ( dom ), max ( dom ), length. out = n) 4 y <- f(x) 5 plot ( x, y,...) 19
6 } 7 8 ### Typowe wywolania 9 styleplot ( sin, c( -pi, pi)) 10 styleplot ( sin, c( -pi, pi), n = 100) 11 styleplot ( sin, c( -pi, pi), n = 100, type = "l") 12 styleplot ( sin, c( -pi, pi), n = 100, type = "o", col = " red ", pch = 20) 20