1 O pakiecie R

R jest obiektowym, interpretowanym, interaktywnym językiem programowania. Jest obecnie podstawowym językiem wykorzystywanym w statystycznej analizie danych. Jest całkowicie darmowy (oparty o licencję GNU).
Pierwsza wersja R została stworzona na początku lat 90-tych przez Roberta Gentlemana i Rossa Ihakę (Wydział Statystyki, Uniwersytet w Auckland, Nowa Zelandia). Od 1997 roku rozwojem projektu kierował zespół ponad 20 ekspertów z różnych dziedzin tj. statystyka, analiza numeryczna czy informatyka. Od tamtego czasu grupa ta znacząco się powiększyła. Ponadto swoje funkcje piszą naukowcy z całego świata.

Na stronie projektu można znaleźć nie tylko najnowszą wersję R, ale również bogatą dokumentację oraz wiele darmowych podręczników: http://www.r-project.org.

1.1 R i RStudio są darmowe - skąd ściągnąć?

R i RStudio są darmowe (miło), można bez przeszkód korzystać z nich w domu. W przypadku zastosowań komercyjnych sugeruję dokładne zapoznanie się z licencją.

Najłatwiej, choć nie jedyny sposób, to użycie strony:

https://posit.co/download/rstudio-desktop/

Pojawi się okno

  1. Najpierw instalujemy R - to co oznaczone “1” na powyższym obrazku. Link przeniesie nas na stronę, gdzie dostępne są wersje R dla Windows, Linux i MacOs. Wybieramy odpowiednią wersję.

  2. Potem instalujemy RStudio, np używając przycisku “2” jak na powyższym rysunku. W dolnej części strony są dostępne wersje RStudio dla innych systemów operacyjnych.

1.1.1 Aktualizacje i reinstalacje

Niestety, czasami zdarzają się różne “dziwne” problemy między innymi ze zgodnością wersji. Czasami najprostszym rozwiązaniem jest aktualizacja (czasami RStudio informuje o nowej wersji przy starcie) lub całkowite odinstalowanie i ponowna instalacja R i RStudio. Wiem, że marna wskazówka, ale paru osobom i kilka razy w pracowni zadziałało.

2 RStudio

RStudio jest edytorem, który ułatwia pracę z R zintegrowanym środowiskiem programistycznym dla języka R. Posiada prosty interfejs użytkownika zbudowany wokół paska menu i kilku okien, którego głównym celem jest zapewnienie skrótów do niektórych z najczęściej używanych poleceń. Oczywiście te same funkcje można wywołać, wpisując odpowiednie polecenia w oknie konsoli. RStudio jest bardzo przydatnym narzędziem ułatwiającym debugowanie, tworzenie pakietów, aplikacji i raportów.

Przykładowy wygląd okna RStudio
Przykładowy wygląd okna RStudio

Okno edycji skryptów umożliwia tworzenie i zapisywanie skryptów.

W oknie Konsoli wyświetlane są wyniki, można tam też wpisywać instrukcje/polecenia.

W prawym dolnym oknie wyświetlane są rysunki (o tym na innych zajęciach) i pomoc.

Prawe górne okno Enviroment - środowisko zawiera m.in. informacje na temat utworzonych zmiennych.

2.1 Konsola

Pojedyncze polecenia (lub ich grupy) można wpisywać w konsoli, zatwierdzając je Enterem.

W konsoli pojawiają się też wyniki działania poleceń.

W konsoli, za pomocą strzałek góra i dół na klawiaturze, można wybrać z historii wcześniej wpisywane instrukcje.

W przypadku większej ilości instrukcji wygodniejsze jest utworzenie skryptu - ciągu poleceń.

2.2 Tworzenie nowego skryptu i zapisanie go

W menu File wybieramy New file a następnie R Script. Plik ten zapisujemy sobie pod wybraną nazwą w wybranym miejscu (tak żeby nie utracić zapisanej pracy).

2.3 Praca ze skryptami

Pojedyncze komendy lub ich grupy wykonuje się poprzez ich zaznaczenie i naciśnięcie Ctrl+Enter lub naciśnięciu przycisku Run (znajdującego się w górnej prawej części okna Edycji skryptów).

2.4 Pliki i raporty R Markdown

(Plikom R Markdown będzie poświęcone osobne laboratorium.)

Do prezentacji wyników, kodów i innych elementów wykonywanych w R wygodne są pliki R Markdown. Umożliwiają one połączenie kodów R, tekstu, grafiki oraz symboli matematycznych.

Z Menu File wybieramy New file a następnie R Markdown….

Pojawi się okienko

gdzie możemy uzupełnić tytuł, autora i datę (można je zmienić później) i klikamy OK. Plik zapisujemy pod wybraną nazwą w OBOWIĄZKOWO wybranym folderze (pojawią się tam dodatkowe pliki, więc lepiej żeby nie był to pulpit, a wybrany, specjalnie utworzony folder).

Kliknięcie przycisku Knit w górnej części okna spowoduje wygenerowanie raportu Markdown oraz utworzenie w folderze pliku html z raportem.

2.4.1 Zadanie

Przejrzeć strukturę pliku źródłowego R Markdown. Zwrócić uwagę na:

  • Preambuła, gdzie można zmienić autora, nazwę oraz datę:

  • tej części kodu - nie ruszamy

  • Możliwość przełączenia między trybami source oraz visual - wypróbować działanie

  • Wpisywanie zwykłego tekstu, nagłówków itp

  • Wpisywanie kodu R - jak zaczniemy pracę, stanie się jasne, co jest kodem R - otoczonego odpowiednimi znacznikami:

  • Dodanie kodu R (znaczników) jest możliwe także za pomocą przycisku w prawej górnej części okna skryptów (zielone C)

2.5 Wybrane ustawienia RStudio

2.5.1 Sprawdzanie pisowni

Warto włączyć sprawdzanie pisowni, czy to w języku polskim czy angielskim. W tym celu wybieramy w menu Tools pozycje Global Options… a następnie:

2.5.2 Wygląd edytora

Wybieramy w menu Tools pozycje Global Options… a następnie:

2.6 Instalowanie i ładowanie dodatkowych pakietów

2.6.1 Polecenie w R do instalowania i ładowania bibliotek

Istotną zaletą R jest duża liczba wyspecjalizowanych bibliotek (pakietów).

Do instalowania bibliotek służy polecenie install.packages(), gdzie w nawiasie podajemy nazwę instalowanej biblioteki. Daną bibliotekę instalujemy tylko raz na danym urządzeniu. Przykład:

install.packages("ggplot2")

Po zainstalowaniu, gdy chcemy skorzystać z biblioteki, musimy za każdym razem dołączyć wybraną bibliotekę poleceniem library():

library(ggplot2)
#lub
library("ggplot2")

2.6.2 Alternatywny sposób instalowania pakietu

Być może wygodniejszy sposób to wybranie z menu Tools polecenia Install Packages... i poprzez okno wyszukiwarki znaleźć odpowiedni pakiet:

Gdy otworzymy skrypt lub plik Markdown, który zawiera niezainstalowany pakiet, pojawia się też monit z informacją o braku pakietu i sugestią jego zainstalowania:

3 Struktury danych

Najczęściej dane w R przyjmują formę wektorów (dzisiaj), list i ramek (kolejne zajęcia).

Wektory są podstawową struktura danych. Każda liczba traktowana jest jako wektor jednoelementowy. Wektory budowane są przy użyciu funkcji c().

3.1 Wektory

Wykonaj i przeanalizuj poniższe komendy wpisując je w górne lewe okno RStudio (skrypt).

Uwaga: część tekstu występująca po znaku # to komentarz.

Pojedyncze komendy lub ich grupy (w skrypcie) wykonuje się poprzez ich zaznaczenie i naciśnięcie Ctrl+Enter lub naciśnięciu przycisku Run (znajdującego się w górnej prawej części okna poleceń).

Przykłady:

c(5,6,1) #Tworzenie wektora
a1<-c(5,6,1) #Przypisanie pod zmienną a1 wektora (5,6,1)
a1 #Wypisanie a1 w oknie konsoli
a2<-c(4.3,-5) #Można użyć znaku = zamiast <-
a=c(a1,a2) # Łączenie wektorów
a #Wypisanie a w oknie konsoli
?c #Wywołanie pomocy na temat funkcji c()
help(c) #Wywołanie pomocy na temat funkcji c()
tekst=c("auto","traktor") #Utworzenie wektora, którego elementami są ciągi znaków

3.2 Wyświetlanie wyników

Gdy chcemy wiedzieć, co zawiera dany obiekt/zmienna, można wpisać jego nazwę, jak w przykładach powyżej. Następnie wyświetlana jest zawartość obiektu w konsoli. W RStudio można również zajrzeć do okna “środowisko” (domyślnie w prawym górnym rogu), które zawiera wszystkie zmienne występujące w środowisku pracy. W tej chwili nasze środowisko pracy zawiera cztery obiekty o nazwach a, a1, a2 i tekst. Są są trzy wektory liczbowe i jeden wektor zawierający zmienne znakowe. Aby uniknąć błędów programistycznych podczas pracy z R, należy regularnie sprawdzać, co znajduje się w tworzonych obiektach. Wykonując kolejne ćwiczenia należy wykonując kolejne linie poleceń sprawdzać, czy zostały utworzone nowe obiekty lub czy istniejące obiekty zostały zmodyfikowane (tak jest, gdy pojawia się znak = lub <-), a gdy tak jest, to co te obiekty zawierają.

3.3 Zarządzanie środowiskiem pracy

Możliwe jest usuwanie utworzonych obiektów za pomocą funkcji rm() lub z menu okna ‘środowisko/Enviroment’ (wyszukując obiekt, a nast. używając przycisku z miotłą). Wykonaj polecenie rm(a2) i sprawdź, czy zmienna a2 zniknęła ze środowiska pracy. Spróbuj usunąć inną zmienną ustawiając w oknie ‘środowisko’ Grid (kliknij strzałkę przy List i zmień na Grid), a następnie zaznacz zmienną do usunięcia i wykorzystaj przycisk miotły. Naciśnięcie przycisku miotły przy opcji List spowoduje usunięcie wszystkich zmiennych. Natomiast kombinacja Ctrl+L czyści konsolę.

Za pomocą polecenia rm(list = ls()) można wyczyścić całe środowisko pracy. Polecenie to można umieścić na początku skryptu R, aby mieć pewność, że pracujemy w “czystym” środowisku.

3.4 Komentarze

Aby dodać komentarz w kodzie/skrypcie R używamy znaku #. Komentarzem jest wtedy cała linijka występująca po tym znaku.

Aby zakomentować blok kodu (kilka linijek) w skrypcie, zaznaczamy wybrane linie kodu, a następnie korzystamy z kombinacji Ctrl+Shift+c. Ponowne użycie tej kombinacji usuwa komentarze z zaznaczonych linijek.

3.5 Operacje na wektorach

Sprawdzić działanie poszczególnych poleceń

a[1] # [ ] jest używany do dostępu do współrzędnych wektora
a[0] # Indeksem pierwszego elementu jest 1 (w Pythonie jest to 0)
a[1]=0 # Przypisuje pierwszej współrzędnej wektora a wartość 0
ind = c(2,4)
a[ind] #Wypisanie 2 i 4 współrzędnej wektora a
a[c(2,4)] #Równoważne wywołanie
d=a[c(1,3,5)] #Wektor d utworzony został z 1, 3 i 5 współrzędnej wektora a
x=3:14 #x jest wektorem 12-sto elementowym postaci o współrzędnych 3,4,…,14
x[1:5]=1 #Przypisanie pierwszym pięciu współrzędnym wektora x wartości 1
2*a #Mnożenie każdej współrzędnej wektora a przez 2
e=3/d #Zauważ, że 1/0 = Inf
f=a-4 #Odejmowanie 4 od każdej współrzędnej wektora a
d1=d+e
d1=d1-e #Zauważ, że Inf-Inf=NaN (“Not a Number”)
d*e #Mnożenie wektorów współrzędna po współrzędnej
e/d #Dzielenie wektorów współrzędna po współrzędnej
sum(d) #Oblicz sumę współrzędnych wektora d
length(d) #Długość wektora d
t(d) #Transpozycja wektora d
t(d)%*%e # %*% jest operatorem mnożenia macierzowego
g=c(sqrt(2),log(10))*(1+exp(2))/cos(8) #R jest również kalkulatorem

3.5.1 Zadanie

Zainicjuj dwa wektory: a=[4,0.5, 7, 0.5] oraz b=[2,0.1,3, 5.2]

  1. Policz średnią dla wektora a.
  2. Policz iloczyn skalarny a \(\circ\) b.
  3. Policz średnią ważoną, elementów wektora a, gdzie wagi są określone w wektorze b.
  4. Oblicz odległość euklidesową pomiędzy wektorami a i b.

3.5.2 Zadanie

Wyjaśnić różnicę w działaniu poleceń 3:n-4 oraz 3:(n-4). Oczywiście, w składni poleceń różnica to nawias, ale dlaczego dostajemy inne wyniki?

n=15
3:n-4
##  [1] -1  0  1  2  3  4  5  6  7  8  9 10 11
3:(n-4)
## [1]  3  4  5  6  7  8  9 10 11

Ważne: Warto zapamiętać powyższą różnicę, bywa ona powodem błędów na przykład przy pisaniu pętli.

3.6 Testy logiczne

1==1
1>2
1!= 2 #!= oznacza “różne od
(1==1) & (1>2) #Symbol & oznacza “i” (koniunkcja warunków)
(1==1) | (1>2) #Symbol | oznacza “lub” (alternatywa warunków)
d==5 #Test na składowych wektora
a>1 & a<=5
ind=(a>1 & a<=5) #Wynik testu jest przypisany do zmiennej ind
is.vector(a) #Funkcja is.vector() zwracająca TRUE jeśli a jest wektorem i FALSE w przeciwnym przypadku
is.numeric(a)
is.character(a)
mode(a) #Zwraca typ obiektu a
a*a
a[1]='test'

a*a #Nie można mnożyć dwóch wektorów, które nie są wektorami liczbowymi (wypróbować polecenie).

3.7 Wyodrębnianie podzbiorów danych

Podczas operacji na zbiorach danych w statystyce często potrzeba np. wyodrębnić osoby o określonych cechach (np. osoby płci męskiej w wieku od 30 do 35 lat pracujące na stanowiskach kierowniczych). Użycie pętli może wydawać się naturalne, ale nie jest optymalne z punktu widzenia czasu obliczeń. Lepiej jest używać operacji przedstawionych w poniższych przykładach. Ogólnie rzecz biorąc, podczas pracy z R należy unikać pętli tak bardzo, jak to tylko możliwe.

- przy pomocy funkcji which()

x=-5:5
x<0
ind=which(x<0) # ind zawiera numery ujemnych współrzędnych x. ‘ind’ to nazwa zmiennej, nie ma jakiegoś istotnego znaczenia.
ind
x[ind]
x[-ind] #znak ‘-’ pozwala uzyskać dopełnienie zbioru indeksów (w tym wypadku numery nieujemnych współrzędnych x)

- bez użycia funkcji which()

x=-5:5
ind=x>0 #Współrzędne ind przyjmują wartości logiczne TRUE (gdy x>0) i FALSE w przeciwnym przypadku)
x[ind] #Zwraca wartości x większe od 0 (czyli te, dla których współrzędne ind miały wartość TRUE)
x[x>=0]
x[x<0]=10 #Zastąpienie wartości ujemnych x przez 10

- wartości brakujące

x=1:10
mean(x)
x[10]=NA #NA (“Not Available”) jest stosowany do kodowania brakujących wartości (niekompletne zbiory danych)
x
mean(x)
mean(x,na.rm = TRUE) #Oblicza średnią z elementów wektora x, pomijając wartości brakujące
is.na(x)
which(is.na(x))

- kilka przydatnych funkcji

Uwaga: poniżej zamieszczamy fragmenty wybrane polecenia oraz, poprzedzone znakami ##, to co powinno pojawić się w konsoli jako wynik operacji

a=rep(1:4,2)

rep(c(1.4,3,5),each=2)
## [1] 1.4 1.4 3.0 3.0 5.0 5.0
seq(0,1, length=11)
##  [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
seq(1.575, 5.125, by=0.05)
##  [1] 1.575 1.625 1.675 1.725 1.775 1.825 1.875 1.925 1.975 2.025 2.075 2.125
## [13] 2.175 2.225 2.275 2.325 2.375 2.425 2.475 2.525 2.575 2.625 2.675 2.725
## [25] 2.775 2.825 2.875 2.925 2.975 3.025 3.075 3.125 3.175 3.225 3.275 3.325
## [37] 3.375 3.425 3.475 3.525 3.575 3.625 3.675 3.725 3.775 3.825 3.875 3.925
## [49] 3.975 4.025 4.075 4.125 4.175 4.225 4.275 4.325 4.375 4.425 4.475 4.525
## [61] 4.575 4.625 4.675 4.725 4.775 4.825 4.875 4.925 4.975 5.025 5.075 5.125
unique(a)
## [1] 1 2 3 4
b=c(5,-2,10,7)

sort(b)
## [1] -2  5  7 10
order(b) #Alternatywna funkcja, która może być użyta do sortowania (przeczytaj informacje w Helpie)
## [1] 2 1 4 3
order(b)[1] #Indeks najmniejszego elementu wektora b.
## [1] 2
order(b)[length(b)] #Indeks największego elementu wektora b.
## [1] 3
max(b)
## [1] 10
which.max(b) #Indeks największego elementu wektora b.
## [1] 3
letters[1:10]
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
abs(b)
## [1]  5  2 10  7
log(abs(b))
## [1] 1.6094379 0.6931472 2.3025851 1.9459101
sqrt(b)
## Warning in sqrt(b): wyprodukowano wartości NaN
## [1] 2.236068      NaN 3.162278 2.645751

4 Zadania

Poniższe ćwiczenia należy wykonać bez użycia pętli!

4.1 Zadanie

Niech \(x = (7, 9, 13, 8, 4, 2, 16, 1, 6, 19, 15, 12, 19, 14, 8, 2, 19, 11, 18, 7)\). Dla każdego z poniższych podpunktów skonstruuj obiekt \(y_i, i=1,...,4\), zawierający:

  1. Drugi element wektora \(x\).

  2. Pierwsze pięć elementów wektora \(x\).

  3. Indeksy \(i\) współrzędnych wektora \(x\), dla których \(x_i >14\).

  4. Wszystkie elementy z wyjątkiem elementów na pozycjach 6, 10 i 12.

4.2 Zadanie

Używając tylko funkcji rep() i seq(), wygeneruj następujące ciągi (możesz użyć funkcji c(), ale nie bezpośrednio (np. nie pisz c(0,6,0,6,0,6) odpowiadając na pierwsze pytanie).

  1. 0 6 0 6 0 6

  2. 1 4 7 10

  3. 1 2 3 1 2 3 1 2 3 1 2 3

  4. 1 2 2 3 3 3

  5. 1 1 1 2 2 3

  6. 1 5.5 10

  7. 1 1 1 1 2 2 2 2 3 3 3 3

4.3 Zadanie

  1. Utwórz wektor \(a = (2.5, 3, 1, 0, 4, -1)\).

  2. Posortuj wektor \(a\) rosnąco za pomocą funkcji sort(). Do czego służy funkcja order? Posortuj wektor \(a\) rosnąco używając funkcji order()?

4.4 Zadanie

Obliczyć średnią harmoniczną wektora \(x = (7, 13, 3, 8, 12, 12, 20, 11)\).

4.5 Zadanie

1.Wygeneruj próbę 50-cio elementową \(x=(x_1,…,x_{50})\) z rozkładu jednostajnego na przedziale \([0,1]\) używając funkcji runif().

  1. Utwórz wektor \(y=(y_1,...,y_{50})\), taki że \(y_i=0,\) gdy \(x_i<0.5\) oraz \(y_i=1\) w przeciwnym przypadku.

  2. Wyznacz liczbę, a następnie proporcję współczynników wektora \(x\), które są większe od 0.5 (w stosunku do całkowitej liczby elementów). Powtórz eksperyment, generując kilkukrotnie próbkę \(x\) i testując różne wartości jej długości \(n\). Czy wyniki są zgodne z Twoją intuicją?

4.6 Zadanie

Ciąg \(y_n=\sum_{i=1}^n \frac{1}{i}-\ln(n)\) jest zbieżny, gdy \(n\rightarrow\infty\). Oblicz wartość \(y_n\) dla n=50, 100, 1000. Wykonaj zadanie używając polecenia mieszczącego się w jednej linii.

4.7 Zadanie

Wiemy, że \(\frac{\pi}{4}=\sum_{k=0}^{\infty}\frac{(-1)^k}{2k+1}\). Znajdź metodę, która pozwala znaleźć przybliżenie liczby \(\pi\) z dokładnością do 6 miejsc po przecinku (polecenie R pi służy do wyświetlenia przybliżonej wartości \(\pi\)).

Wskazówka:

Można zacząć od wygenerowania wektorów postaci (1,-1,1,-1,...) oraz (1,3,5,7,...) o ustalonej długości, a dopiero później zająć się ilorazem i sumą.

Dokładność można sprawdzić obliczając różnicę (a dokładniej, jej wartość bezwzględną) między uzyskanym wynikiem, a wartością przybliżaną.