Dariusz Brzeziński
Część II
Slajdy oparte o materiały stworzone przez Rogera Penga.
W R są trzy podstawowe operatory, które można wykorzystać do filtrowania obiektów:
[
służy do filtrowania wektorów,[[
pozwala wybierać elementy listy lub data frame'a,$
pozwala odczytywać elementy listy lub data frame'a po nazwie.> x <- c("a", "b", "c", "c", "d", "a")
> x[1]
[1] "a"
> x[2]
[1] "b"
> x[1:4]
[1] "a" "b" "c" "c"
> x[x > "a"]
[1] "b" "c" "c" "d"
> u <- x > "a"
> u
[1] FALSE TRUE TRUE TRUE TRUE FALSE
> x[u]
[1] "b" "c" "c" "d"
Macierze (i data frame'y) można filtrować za pomocą indeksów (i,j).
> x <- matrix(1:6, 2, 3)
> x[1, 2]
[1] 3
Gdy pominiemy indeks, brane są wszystkie wartości z danego wymiaru.
> x[1, ]
[1] 1 3 5
> x[, 2]
[1] 3 4
> x <- list(foo = 1:4, bar = 0.6)
> x[1]
$foo
[1] 1 2 3 4
> x[[1]]
[1] 1 2 3 4
> x$bar
[1] 0.6
> x[["bar"]]
[1] 0.6
> x["bar"]
$bar
[1] 0.6
> x <- list(foo = 1:4, bar = 0.6, baz = "halo")
> x[c(1, 3)]
$foo
[1] 1 2 3 4
$baz
[1] "halo"
Operator [[
może korzystać ze zmiennych, operator $
przyjmuje tylko literały.
> x <- list(foo = 1:4, bar = 0.6, baz = "halo")
> name <- "foo"
> x[[name]] ## indeks ‘foo’ w zmiennej
[1] 1 2 3 4
> x$name ## nie ma indeksu o nazwie ‘name’!
NULL
> x$foo
[1] 1 2 3 4 ## jest element o nazwie ‘foo’
Choć nie jest to polecane, operatory [[
i $
mogą wykorzystać częściowe dopasowanie.
Warunek: dopasowanie musi być jednoznaczne.
> x <- list(aardvark = 1:5)
> x$a
[1] 1 2 3 4 5
> x[["a"]]
NULL
> x[["a", exact = FALSE]]
[1] 1 2 3 4 5
Często wykonywanym filtrowaniem jest usuwanie brakujących wartości (NA
).
> x <- c(1, 2, NA, 4, NA, 5)
> bad <- is.na(x)
> x[!bad]
[1] 1 2 4 5
A co jeśli mamy wiele obiektów i chcemy zostawić tylko podzbiór bez żadnych brakujących wartości w żadnym z obiektów?
> x <- c(1, 2, NA, 4, NA, 5)
> y <- c("a", "b", NA, "d", NA, "f")
> good <- complete.cases(x, y)
> good
[1] TRUE TRUE FALSE TRUE FALSE TRUE
> x[good]
[1] 1 2 4 5
> y[good]
[1] "a" "b" "d" "f"
> airquality[1:6, ]
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
> good <- complete.cases(airquality)
> airquality[good, ][1:6, ]
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
7 23 299 8.6 65 5 7
R zawiera wszystkie podstawowe instrukcje sterujące jakich spodziewamy się po języku programowania:
if
, else
: warunkifor
: pętle while
: więcej pętli repeat
: jeszcze więcej pętlibreak
: instrukcje przerywania pętlinext
: instrukcje kontynuowania pętlireturn
: zwracanie wartościTo jest poprawny if-else:
if(x > 3) {
y <- 10
} else {
y <- 0
}
To też:
y <- if(x > 3) {
10
} else {
0
}
Trzy równoważne pętle for:
x <- c("a", "b", "c", "d")
for(i in 1:4) {
print(x[i])
}
for(i in seq_along(x)) {
print(x[i])
}
for(letter in x) {
print(letter)
}
Pętle while
zaczynają się od sprawdzenia warunku i kolejne wykonania pętli ponownie
sprawdzają czy pętla ma być dalej wykonywana.
count <- 0
while(count < 10) {
print(count)
count <- count + 1
}
Jak to przy pętlach while, trzeba uważać na warunek zatrzymania.
repeat
to odpowiednik pętli do-while. Jest to chyba najrzadziej wykorzystywana pętla,
bo wymaga jawnego przerwania instrukcją break
.
x0 <- 1
tol <- 1e-8
repeat {
x1 <- computeEstimate()
if(abs(x1 - x0) < tol) {
break
} else {
x0 <- x1
}
}
next
pozwala pominąć część kroku pętli (jest to odpowiednik instrukcji continue)
for(i in 1:100) {
if(i <= 20) {
## Pomiń pierwsze 20 iteracji
next
}
## Zrób coś później
}
return()
zwraca wartość i wychodzi z funkcji… tak… return()
w R jest funkcją…
Funkcje w R tworzy się za pomocą dyrektywy function()
i przypisuje do zmiennej jak każdy inny obiekt. W praktyce funkcje w R są obiektami typu “function”.
f <- function(<argumenty>) {
## Powtarzalne zadanie
}
Funkcje w R:
Funkcje mają nazwane argumenty, które mogą mieć wartości domyślne. Argumenty zdefiniowane w sygnaturze funkcji to argumenty formalne.
Nie każde wywołanie musi podawać wartości wszystkich argumentów formalnych - mogą być brakujące lub mieć wartość domyślną.
Argumenty mogą być dopasowane przez pozycję lub nazwę. Wszystkie poniższe wywołania
funkcji sd
są równoważne.
> mydata <- rnorm(100)
> sd(mydata)
> sd(x = mydata)
> sd(x = mydata, na.rm = FALSE)
> sd(mydata, na.rm = FALSE)
> sd(na.rm = FALSE, x = mydata)
> sd(na.rm = FALSE, mydata)
Choć jest to dopuszczalne, nie zaleca się mieszania kolejności parametrów.
Jak wiele dopasowań w R, również dopasowanie argumentów może być częściowe. Kolejne czynności przy określaniu dopasowania to:
f <- function(a, b = 1, c = 2, d = NULL) {
}
Oprócz nie ustawiania wartości domyślnej, można też jawnie przypisać wartość NULL
.
Argumenty funkcji są wymagane dopiero gdy są potrzebne.
f <- function(a, b) {
a^2
}
f(2) #nie ma problemu, bo b jest niepotrzebne
[1] 4
Argumenty funkcji są wymagane dopiero gdy są potrzebne.
f <- function(a, b) {
print(a) # to się wykona
print(b) # tu rzuci błędem
}
f(45) # jest problem bo b jest potrzebne
Argument … oznacza zmienną liczbę argumentów.
myplot <- function(x, y, type = "l", ...) {
plot(x, y, type = type, ...)
}
> mean
function (x, ...)
UseMethod("mean")
Przydatne również gdy nie znamy liczby parametrów, które zostaną przekazane.
> args(paste)
function (..., sep = " ", collapse = NULL)
> args(cat)
function (..., file = "", sep = " ", fill = FALSE, labels = NULL, append = FALSE)
Drobna niedogodność polega na tym, że po … argumenty muszą być jawnie nazwane przy wywołaniu i muszą być w pełni dopasowane.
> args(paste)
function (..., sep = " ", collapse = NULL)
> paste("a", "b", sep = ":")
[1] "a:b"
> paste("a", "b", se = ":")
[1] "a b :"
R tworzy zakresy statyczne. Zakresy nazw są tworzone przez:
=
, <-
),=
, <-
),<<-
).Warto zaznaczyć, że w R funkcje mogą być zagnieżdżane oraz że funkcje mogą zwracać funkcje.
Pętle są przydatne podczas programowania, ale trudne do wykorzystania podczas interaktywnej pracy ze zbiorem danych. Zamiast pętli można wykorzystać funkcje z rodziny apply:
lapply
: wykonuje funkcję na elementach listysapply
/vapply
: to co lapply
tylko z upraszczaniemapply
: wywołuje funkcję na wybranych wymiarachtapply
: wykonuje funkcję z podziałem na grupymapply
: to co sapply
, ale dla wielu list/macierzyx <- list(a=1:9, b=rnorm(10), c=rnorm(9, 5))
lapply(x, mean)
$a
[1] 5
$b
[1] 0.3148138
$c
[1] 4.880512
W R można debugować w konsoli.
traceback
: wypisuje stos wywołańdebug
: oznacza funkcję do inspekcjibrowser
: wstrzymuje wykonanie funkcji i przełącza w tryb debugowaniatrace
: pozwala wtłoczyć kod debugujący (browser
, recover
) do funkcji recover
: pozwala debugować po wystąpieniu błęduWykonujemy kolejne lekcje (wszystkie do końca modułu Programowanie w R):
library(swirl.pl)
swirl()