# Načtení balíčku tidyverse (tidyverse je vlastně sada více balíčků)
library(tidyverse)
R lze využít jako kalkulačku. Podobné symboly pro matematické operace využívá i Excel.
# Sčítání
5 + 50
#> [1] 55
# Odčítání
5 - 5
#> [1] 0
# Násobení
3 * 5
#> [1] 15
# Dělení
5 + 5) / 2
(#> [1] 5
# Umocňování
2^10
#> [1] 1024
# Odmocňování
sqrt(9)
#> [1] 3
9^(1/2)
#> [1] 3
8^(1/3)
#> [1] 2
# Celočíselné dělení
16 %/% 6
#> [1] 2
# Zbytek po celočíselném dělení
16 %% 6
#> [1] 4
Psaní symbolů na české klávesnici skrze pravý alt:
Alternativa - přepnutí na anglickou klávesnici, kde jsou tyty symboly dostupnější.
%>%
(nověji |>
)Objekt reprezentují hodnoty (např. “0” nebo “Jablko”) nebo jiné objekty. Např. dataset je objekt obsahující jiné objekty, tj. jednotlivé proměnné.
Nové objekty lze vytvářet pomocí <- ve formě:
object_name <- value
Při pojmenování objektů doporučuji používat tzv. snake_case: nepužívat velká písmena a jednotlivá slova/výrazy oddělovat pomocí underscore
# Přidělit objektu x hodnotu 42
<- 42
x
# vyvolat/prozkoumat objekt lze jenoduše napsáním jeho jména
x#> [1] 42
<- 666
r_rocks
# Proč tento kód nefunguje? Je R "case sensitive"?
r_rock#> Error in eval(expr, envir, enclos): object 'r_rock' not found
R_rocks#> Error in eval(expr, envir, enclos): object 'R_rocks' not found
# Jde to i naopak?
33 -> y
y#> [1] 33
# Změňte hodnotu my_numeric na vaše oblíbené číslo
<- 17
my_numeric
my_numeric#> [1] 17
# Změňte hodnotu my_character např. na jméno vaší oblíbené kapely
<- c("Iron Maiden")
my_character
my_character#> [1] "Iron Maiden"
# Změňte hodnotu my_logical na FALSE
<- TRUE
my_logical
my_logical#> [1] TRUE
# Vyvolejte proměnné my_numeric, my_character i my_logical
# Aplikujte funkci typeof() na objekty my_numeric, my_character i my_logical
Jednou z nejpoužívanějších funkcí je funkce c()
(combine, concatenate), která umožňuje sloučit více prvků dohromady čili
vytvářet vektory o délce větší než 1.
<- c(8, 5, 9, 10, 16)
x
x#> [1] 8 5 9 10 16
Existují dva základní typy vektorů. Atomické vektory (atomic vectors) a listy (lists). Nejdůležitějšími atomickými vektory jsou vektory logické (logical), celá čísla (integer) a reálná čísla (double). Hlavní rozdíl mezi atomickými vektory a listy je ten, že atomické vektory jsou homogenní (všechny prvky jsou stejného typu, např. pouze celá čísla). O atomických vektorech lze uvyžovat jako o jednotlivých proměnných.
Každý vektor má dvě hlavní vlastnosti:
typeof()
;lenght()
# letters ja zabudovaný vektor typu character se základními písmeny abecedy
letters#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
#> [20] "t" "u" "v" "w" "x" "y" "z"
typeof(letters)
#> [1] "character"
1:10
#> [1] 1 2 3 4 5 6 7 8 9 10
typeof(1:10)
#> [1] "integer"
typeof(c(TRUE, FALSE, TRUE))
#> [1] "logical"
<- list("a", "b", 1:10)
x length(x)
#> [1] 3
typeof(x)
#> [1] "list"
length(1:10)
#> [1] 10
length(letters)
#> [1] 26
typeof(c(TRUE, FALSE, 1, 5))
#> [1] "double"
c(TRUE, FALSE, 1, 5)
#> [1] 1 0 1 5
Vektory také mohou obsahovat různá metadata ve formě tzv. atributů. Tyto atributy využívají tzv. augmentované vektory, jimiž jsou například:
Vektory typu logical jsou nejjednodušším typem
atomických vektorů, protože mohou nabývat pouze tří možných hodnot:
TRUE
, FALSE
a NA
, tj. pravda,
nepravda a NA jako chybající hodnota (not available)
c(TRUE, TRUE, FALSE, NA)
#> [1] TRUE TRUE FALSE NA
Mezi numerické vektory (numeric) se řadí vektory typu integer a double čili celá čísla a reálná čísla. Defaultně R vytváří vektory typu double, abychom vytvořili vektor typu integer, musíme za číslo doplnit písmeno L. Také při generování sekvence číšel pomocí dvojtečky je výstupem vektor typu integer.
typeof(1)
#> [1] "double"
typeof(1L)
#> [1] "integer"
typeof(1:10)
#> [1] "integer"
Obvykle není potřeba mezi integers a doubles rozlišovat, ale je třeba mít na paměti, že doubles jsou pouze aproximace. Protože paměť počítače není nekonečná, pamatuje si jen určitý počet desetinnýh míst, a proto se R nemusí někdy chovat tak, jak bychom očekávali.
<- sqrt(2) ^ 2
x
x#> [1] 2
- 2
x #> [1] 4.440892e-16
== 2
x #> [1] FALSE
# Funkce near počítá s nějakou (velmi malou) tolerancí
near(x, 2)
#> [1] TRUE
Vektory typu character jsou nejkomplexnější, protože mohou zahrnovat jakékoli znaky (řetězce znaků) a počet těchto znaků je téměř neomezený.
<- "This is a reasonably long string."
x
x#> [1] "This is a reasonably long string."
Existují dva způsoby, jak kovertovat jeden typ vektoru v jiný: explicitně a implicitně.
Explicitní konverze znamená, že použijeme použijeme
přímo funkce k tomu určené, např. as.logical()
,
as.integer()
, as.double()
nebo
as.character()
as.integer(c(TRUE, FALSE, TRUE))
#> [1] 1 0 1
as.character(c(1, 2, 3, 4))
#> [1] "1" "2" "3" "4"
as.logical(c(0, 1, 0, 1))
#> [1] FALSE TRUE FALSE TRUE
as.double(c("0.1", "1.5", "3.6"))
#> [1] 0.1 1.5 3.6
Implicitní konverze znamená, že použijeme vektor ve specifickém kontextu, který očekává určitý typ vektoru
<- sample(1:20, 100, replace = TRUE)
x # číselný vektor
x #> [1] 8 1 7 12 17 20 14 15 20 9 17 8 11 3 2 18 20 18 5 8 9 3 9 19 9
#> [26] 9 4 17 4 5 16 6 17 14 4 2 4 4 7 16 12 11 4 5 6 9 14 7 19 10
#> [51] 6 6 20 12 5 3 14 17 19 17 4 13 11 13 20 13 14 2 12 10 12 15 2 19 2
#> [76] 3 10 5 1 10 16 11 17 5 13 9 7 1 1 18 14 3 5 4 8 11 16 4 9 20
<- x > 10
y # logický vektor TRUE/FALSE
y #> [1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE FALSE
#> [13] TRUE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE TRUE
#> [25] FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE
#> [37] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE FALSE
#> [49] TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE
#> [61] FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE FALSE TRUE TRUE
#> [73] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE
#> [85] TRUE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE TRUE
#> [97] TRUE FALSE FALSE TRUE
# prvky, pro které podmínka platí – TRUE
# prvky, pro které podmínka neplatí – TRUE
# Implicitní konverze TRUE na 1 a FALSE na 0 při použití funkcí sum() a mean()
sum(y)
#> [1] 46
mean(y)
#> [1] 0.46
Při tvorbě vektorů s více prvky pomocí funkce c() má vždy přednost složitější typ, protože převod jednoduššího typu vektoru na složitější je možný, ale naopak to často není možné (nedávalo by např. smysl převádět věty na celá čísla).
c(TRUE, 0L)
#> [1] 1 0
typeof(c(TRUE, 0L))
#> [1] "integer"
c(TRUE, 0L, 2.5)
#> [1] 1.0 0.0 2.5
typeof(c(TRUE, 0L, 2.5))
#> [1] "double"
c(TRUE, 0L, 2.5, "one")
#> [1] "TRUE" "0" "2.5" "one"
typeof(c(TRUE, 0L, 2.5, "one"))
#> [1] "character"
Často potřebujeme vektory nějak transformovat, sumarizovat apod., ale operace, kterou chceme provést, závisí na typu vektoru. Prvním ze způsobů, jak ověřit typ vektoru, je funkce typeof(), která vrací typ vektoru.
typeof(c(TRUE, FALSE))
#> [1] "logical"
Druhým způsobem jsou testovací funkce, které vracejí hodnoty
TRUE
nebo FALSE
, podle toho, zda je testovaný
vektor daného typu.
is_logical(c(TRUE, FALSE))
#> [1] TRUE
is_logical(c(0, 1))
#> [1] FALSE
is_integer(c(1L, 2L))
#> [1] TRUE
is_integer(c(1, 2))
#> [1] FALSE
is_double(c(1.2, 2.4))
#> [1] TRUE
is_double(c(1L, 2L))
#> [1] FALSE
is_numeric(c(1.2, 2.4))
#> Warning: Deprecated
#> [1] TRUE
is_numeric(c(1L, 2L))
#> Warning: Deprecated
#> [1] TRUE
is_character(c("1", "2"))
#> [1] TRUE
is_character(c(1, 2))
#> [1] FALSE
is_atomic(c(1, 2))
#> [1] TRUE
is_atomic(list(1, c(1, 2)))
#> [1] FALSE
is_list(c(1, 2))
#> [1] FALSE
is_list(list(1, c(1, 2)))
#> [1] TRUE
is_vector(c(1, 2))
#> [1] TRUE
is_vector(NULL)
#> [1] FALSE
Každé zřejmě uhádne, co se stane, když sečteme (vynásobíme, odečteme apod.) vektory stejné délky
c(1, 2, 3) + c(4, 5, 6)
#> [1] 5 7 9
c(1, 2, 3) * c(4, 5, 6)
#> [1] 4 10 18
c(1, 2, 3) / c(4, 5, 6)
#> [1] 0.25 0.40 0.50
Co když ale vektory nemají stejnou délku? Kromě implicitní konverze typů vektorů si R také implicitně vynutí stejnou délku vektorů. Tomu se říká recyklace, protože prvky kratšího vektoru (toho s méně prvky) jsou opakovány, dokud jeho délka neodpovídá délce vektoru s více prvky.
# Tyto operace jsou tedy ekvivaletní
c(1, 2, 3) + 10
#> [1] 11 12 13
c(1, 2, 3) + c(10, 10, 10)
#> [1] 11 12 13
1:10 + 1:2
#> [1] 2 4 4 6 6 8 8 10 10 12
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)
#> [1] 2 4 4 6 6 8 8 10 10 12
1:10 + 1:3
#> Warning in 1:10 + 1:3: longer object length is not a multiple of shorter object
#> length
#> [1] 2 4 6 5 7 9 8 10 12 11
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1)
#> [1] 2 4 6 5 7 9 8 10 12 11
Prvky jakéhokoli typu vektoru lze pojmenovat, a to už při jeho vytváření. Jména jsou jedním z možných atributů vektoru.
<- c(x = 1, y = 2, z = 4)
x
x#> x y z
#> 1 2 4
names(x)
#> [1] "x" "y" "z"
attributes(x)
#> $names
#> [1] "x" "y" "z"
Jména prvků lze doplnit i poté, co byl vektor vytvořen.
<- c(1, 2, 4)
x
x#> [1] 1 2 4
# Jeden z možných způsobů
names(x)
#> NULL
names(x) <- c("x", "y", "z")
x#> x y z
#> 1 2 4
names(x)
#> [1] "x" "y" "z"
# Další z možných způsobů
<- c(1, 2, 4)
x <- set_names(x, c("x", "y", "z"))
x
x#> x y z
#> 1 2 4
Existují tři hlavní způsoby, jak vybrat prvky jednoho vektoru pomocí jiného vektoru. Všechny z nich ale používají hranaté závorky.
Zaprvé, pomocí jiného, celočíselného vektoru.
<- c("one", "two", "three", "four", "five")
x
x#> [1] "one" "two" "three" "four" "five"
c(3, 2, 5)]
x[#> [1] "three" "two" "five"
# Opakováním čísel/pozic můžete vytvořit delší vektor, než byl vektor vstupní
c(1, 1, 1, 5, 5, 5, 2)]
x[#> [1] "one" "one" "one" "five" "five" "five" "two"
# Záporné hodnoty vedou k vyřazení prvků na daných pozicích
c(-1, -3, -5)]
x[#> [1] "two" "four"
-c(1, 3, 5)] # snadnější zápis
x[#> [1] "two" "four"
# Ale nejde mísit dohromady kladné a záporné hodnoty
c(1, -1)]
x[#> Error in x[c(1, -1)]: only 0's may be mixed with negative subscripts
Zadruhé, pomocí logického vektoru, kdy jsou zachovány všechny prvky, kterým koresponduje hodnota TRUE. To je nejužitečnější s využitím srovnávacích funkcí a logických operátorů, jako jsou:
<- c(10, 3, NA, 5, 8, 1, NA)
x
x#> [1] 10 3 NA 5 8 1 NA
c(TRUE, TRUE, FALSE, FALSE, FALSE)]
x[#> [1] 10 3 1 NA
c(TRUE, FALSE)] # Opět dochází k recyklaci, takže je vybrán každý lichý prvek
x[#> [1] 10 NA 8 NA
# Všechny hodnoty vyšší než 5 (ponechá i missing values)
> 5]
x[x #> [1] 10 NA 8 NA
# Všechny hodnoty dělitelné dvěmi (opět ponechá i missing values)
%% 2 == 0]
x[x #> [1] 10 NA 8 NA
K ověření toho, zda je nějaký prvek missing value, je nutné použít
funkci is.na()
(tím se eRka ptáme je prvek
chybějící?), nikoli x[x == NA]
(tím bychom se eRka
ptali. jestli má prvek určitou hodnotu, ale neřekli bychom mu jakou,
takže výsledkem by byl jen vektor NA
).
# Toto nefunguje, jak bychom asi očekávali
== NA]
x[x #> [1] NA NA NA NA NA NA NA
# Jak tedy vybrat všechny nechybějící prvky?
is.na(x) # funkce is.na() vrací TRUE, když je prvek NA (missing value)
#> [1] FALSE FALSE TRUE FALSE FALSE FALSE TRUE
!is.na(x) # pomocí výkřičníku můžeme negovat
#> [1] TRUE TRUE FALSE TRUE TRUE TRUE FALSE
!is.na(x)] # výběr všech non-missing values
x[#> [1] 10 3 5 8 1
Zatřetí, pokud jsou prvky vektoru pojmanovány, můžeme k výběru prvků použít jiný vektor typu character.
<- c(abc = 1, def = 2, xyz = 5)
x
c("xyz", "def")]
x[#> xyz def
#> 5 2
c("xyz", "xyz", "xyz")]
x[#> xyz xyz xyz
#> 5 5 5
Kromě hranatých závorek je možné použít i dvojité hranaté závorky.
Použití [[
vždy vybere pouze jediný prvek vektoru
(kdybychom se pokoušeli vybrat více prvků, vyústí to v chybové hlášení)
a také vždy vymaže jméno prvku.
mean(is.na(x))
o vektoru x?[
a [[
, když
subsetujeme neexistující prvky?<- c(1, 2, 3, NA)
x is.na(x)
#> [1] FALSE FALSE FALSE TRUE
mean(is.na(x))
#> [1] 0.25
mean(!is.na(x))
#> [1] 0.75
<- c(a = 10, b = 20)
x 1:5]
x[#> a b <NA> <NA> <NA>
#> 10 20 NA NA NA
c("a", "b", "c", "d", "e")]
x[#> a b <NA> <NA> <NA>
#> 10 20 NA NA NA
3]
x[#> <NA>
#> NA
3]]
x[[#> Error in x[[3]]: subscript out of bounds
# Na tomto vektoru si vyzkoušejte různé logické operátory
set.seed(123)
<- sample(1:20, size = 100, replace = TRUE) x
Listy jsou komlexnější než atomické vektory, protože mohou obsahovat jiné listy nebo atomické vektory. Jsou tak ideální pro tvorbu hierarchických datových struktur.
<- list(1, c(2, 3), c("A", "B", "C"))
x
x#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 2 3
#>
#> [[3]]
#> [1] "A" "B" "C"
Velmi užitečná je funkce str()
, protože zobrazuje
strukturu listu.
str(x)
#> List of 3
#> $ : num 1
#> $ : num [1:2] 2 3
#> $ : chr [1:3] "A" "B" "C"
<- list(a = 1, b = 2, c = 3)
x_named str(x_named)
#> List of 3
#> $ a: num 1
#> $ b: num 2
#> $ c: num 3
Jak bylo naznačeno. Na rozdíl od atomických vektorů mohou listy obsahovat směs různých typů objektů. Dokonce i jiné listy.
<- list("a", 1L, 1.5, TRUE)
y str(y)
#> List of 4
#> $ : chr "a"
#> $ : int 1
#> $ : num 1.5
#> $ : logi TRUE
<- list(list(1, 2), list(3, 4))
z str(z)
#> List of 2
#> $ :List of 2
#> ..$ : num 1
#> ..$ : num 2
#> $ :List of 2
#> ..$ : num 3
#> ..$ : num 4
Existují tři způsoby, jak subsetovat list (vybrat prvky listu).
Jejich použití si můžeme ukázat na listu à
<- list(
a a = 1:3,
b = "a string",
c = pi,
d = list(-1, -5)
)
str(a)
#> List of 4
#> $ a: int [1:3] 1 2 3
#> $ b: chr "a string"
#> $ c: num 3.14
#> $ d:List of 2
#> ..$ : num -1
#> ..$ : num -5
Pomocí [
vytvoříme list s vybranými prvky. Zachováváme
tedy list jako typ outputu. Je to, jako bychom z původního listu
“vyházeli” prvky, které nepotřebujeme.
1:2]
a[#> $a
#> [1] 1 2 3
#>
#> $b
#> [1] "a string"
4]
a[#> $d
#> $d[[1]]
#> [1] -1
#>
#> $d[[2]]
#> [1] -5
str(a[1:2])
#> List of 2
#> $ a: int [1:3] 1 2 3
#> $ b: chr "a string"
str(a[4])
#> List of 1
#> $ d:List of 2
#> ..$ : num -1
#> ..$ : num -5
Pomocí [[
jakoby “vyřízneme” prvek listu a odstraníme
přitom jednu úroveň hierarchie.
str(a[[1]])
#> int [1:3] 1 2 3
1]]
a[[#> [1] 1 2 3
Pokud mají prvky listu jména, můžeme subseting provést takto:
# Výběr více prvků
c("a", "b")]
a[#> $a
#> [1] 1 2 3
#>
#> $b
#> [1] "a string"
# Vyříznutí jednoho prvku
"b"]]
a[[#> [1] "a string"
$b
a#> [1] "a string"
Faktory (factors) jsou určeny k reprezentaci kategorických
proměnných, tj. proměnných, které mohou nabývat jen několika jedinečných
hodnot. Zjednodušeně řečeno, faktory jsou eRkovské označení pro
kategorické proměnné. Jejich základem je vektor typu integer, ale jsou
“augmentovaný” o aribut levels
, který definuje úrovně a
jejich pořadí.
<- c("cold", "hot", "hot", "warm", "cold", "cold", "warm")
temps factor(temps)
#> [1] cold hot hot warm cold cold warm
#> Levels: cold hot warm
Defaultní je pořadí podle abecedy. Ale pomocí argumentu levels jej můžeme změnit
<- factor(temps,
temps_fct levels = c("cold", "warm", "hot"))
temps_fct#> [1] cold hot hot warm cold cold warm
#> Levels: cold warm hot
Často jsou jednotlivé kategorie nejprve kódovány numericky a jejich labely doplněny pomocí argumentu labels.
<- c(1, 3, 3, 2, 1, 1, 2)
temps
temps#> [1] 1 3 3 2 1 1 2
<- factor(temps,
temps_fct levels = c(1, 2, 3),
labels = c("cold", "warm", "hot"))
temps_fct#> [1] cold hot hot warm cold cold warm
#> Levels: cold warm hot
Matice (matrix) je v eRku také atomický vektor, protože může zahrnovat pouze prvky stejného typu (např. jen reálná čísla), ale opět jde o “agumentovaný” atomický vektor, protože má dvě dimenze: řádky a sloupce. Je tedy dvoudimenzionální.
Takto lze v eRku pomocí funkce matrix() vytvořit matici. Argument
byrow
specifikuje, zda chceme matici plnit po řádcích.
Argumenty nrow
a ncol
specifikují, kolik řádků
nebo sloupců má matice mít. Stačí vyplnit jen jeden z nich, protože
pokud máme např. 12 prvků a mají se rozdělit do tří řádků, je jasné, že
sloupce musejí být čtyři.
# Nejprve vytvoříme atomický vektor
<- 1:12
x
x#> [1] 1 2 3 4 5 6 7 8 9 10 11 12
matrix(x, byrow = TRUE, nrow = 3)
#> [,1] [,2] [,3] [,4]
#> [1,] 1 2 3 4
#> [2,] 5 6 7 8
#> [3,] 9 10 11 12
matrix(x, byrow = FALSE, nrow = 3)
#> [,1] [,2] [,3] [,4]
#> [1,] 1 4 7 10
#> [2,] 2 5 8 11
#> [3,] 3 6 9 12
matrix(x, byrow = FALSE, ncol = 2)
#> [,1] [,2]
#> [1,] 1 7
#> [2,] 2 8
#> [3,] 3 9
#> [4,] 4 10
#> [5,] 5 11
#> [6,] 6 12
Jednotlivé prvky matice pojmenovat nelze, ale můžeme pojmenovat její řádky a sloupce, buďto rovnou při jejím vytváření (pomocí argumentu dimnames, což musí být list obsahující dva atomické vektory odpovídající délky), nebo dodatečně pomocí funkce dimnames(), resp. colnames() a rownames()
# Již při vytváření
<- matrix(x, byrow = FALSE, nrow = 3,
m dimnames = list(
c("row1", "row2", "row3"), # vektor s labely pro řádky matice
c("col1", "col2", "col3", "col4") # vektor s labely pro sloupce matice
)
)
m#> col1 col2 col3 col4
#> row1 1 4 7 10
#> row2 2 5 8 11
#> row3 3 6 9 12
# Dodatečně
<- matrix(x, byrow = FALSE, nrow = 3)
m
m#> [,1] [,2] [,3] [,4]
#> [1,] 1 4 7 10
#> [2,] 2 5 8 11
#> [3,] 3 6 9 12
dimnames(m) <- list(c("row1", "row2", "row3"), # vektor s labely pro řádky matice
c("col1", "col2", "col3", "col4")) # vektor s labely pro sloupce matice
m#> col1 col2 col3 col4
#> row1 1 4 7 10
#> row2 2 5 8 11
#> row3 3 6 9 12
<- matrix(x, byrow = FALSE, nrow = 3)
m rownames(m) <- c("row1", "row2", "row3")
colnames(m) <- c("col1", "col2", "col3", "col4")
m#> col1 col2 col3 col4
#> row1 1 4 7 10
#> row2 2 5 8 11
#> row3 3 6 9 12
Protože matice je vlastně atomický vektor, můžeme selektovat její prvky podobně jako u jiných atomických vektorů pomocí hranatých závorek. Ale protože má dvě dimenze, rozlišujeme výběr řádků a sloupců. Nejlepší je ukázat si to názorně.
1, 2] # Výběr hodnot z prvního řádku a druhého sloupce
m[#> [1] 4
c(1,2), c(1,2)] # Výběr hodnot z prvních dvou řádků a sloupců
m[#> col1 col2
#> row1 1 4
#> row2 2 5
3] # Výběr všech řádků třetího sloupce
m[ , #> row1 row2 row3
#> 7 8 9
K výběru také můžeme poutíž logické vektory nebo textové vektory (má-li matice pojmenované řádky/sloupce)
c(TRUE, FALSE, FALSE), c(FALSE, FALSE, TRUE, TRUE)]
m[#> col3 col4
#> 7 10
"row2", c("col3", "col4")]
m[#> col3 col4
#> 8 11
Anebo jinou matici logických hodnot se shodnými dimenzemi.
<- matrix(
m_logical c(TRUE, FALSE, FALSE, TRUE,
FALSE, TRUE, TRUE, FALSE,
TRUE, FALSE, FALSE, TRUE),
byrow = TRUE, nrow = 3)
m_logical#> [,1] [,2] [,3] [,4]
#> [1,] TRUE FALSE FALSE TRUE
#> [2,] FALSE TRUE TRUE FALSE
#> [3,] TRUE FALSE FALSE TRUE
m[m_logical]#> [1] 1 3 5 8 10 12
Budeme se zabývat počtem “cursing words” v několika filmech Q. Tarantina.
# Názvy filmů
<- c("Django Unchained", "Inglorious Basterds", "Jackie Brown",
movies "Kill Bill: Vol. 1", "Kill Bill: Vol. 2", "Pulp Fiction",
"Reservoir Dogs")
# Počty slov
<- c(262, 58, 368, 57, 69, 469, 421)
profanities
profanities#> [1] 262 58 368 57 69 469 421
profanities
vektorem
movies
Zaznamenáme si, kolikrát v jednotlivých filmech zazněla slova “hell” a “goddamn”
<- c(10, 4, 10, 3, 1, 2, 12)
hell <- c(28, 8, 27, 7, 5, 28, 10) goddamn
spirituality
jako součet obou
vektorů.Doplníme si údaje o počtu zachycených úmrtí.
<- c(47, 48, 4, 63, 11, 7, 10)
deaths names(deaths) <- movies
deaths#> Django Unchained Inglorious Basterds Jackie Brown Kill Bill: Vol. 1
#> 47 48 4 63
#> Kill Bill: Vol. 2 Pulp Fiction Reservoir Dogs
#> 11 7 10
profanities
a deaths
.
Náležitě také pojmenujte řádky a sloupce matice.colSums()
,
colMeans()
, rowSums()
a
rowMeans()
. Co tyto funkce počítají?cbind()
přidejte do matice vektor
year
s roky premiéry filmů jako nový sloupec:<- c(2012, 2009, 1997, 2003, 2004, 1994, 1992) year
rbind()
přidejte do matice vektor
The Hateful Eight
s údaji o novém filmu:`The Hateful Eight` <- c(107, 20, 2015)
Dataframe je matice tak, jak ji chápeme při analýze dat. Dataframe je uspořádán do sloupců a řádků, přičemž řádky odpovídají pozorováním/případům a sloupce proměnným. Technicky je dataframe typ listu, protože může obsahovat různé typy vektorů, ale je omezen tím, že jeho prvky (sloupce) musejí mít stejnou délku.
Balíčky v R obsahují i různé dataframy
data() # Přehled zabudovaných datasetů
data(USArrests) # Vyvolání zabudovaného datasetu
View(USArrests) # Prohlížení v RStudiu
K orientaci v dataframu slouží několik funkcí (tyto funkce lze použít i pro jiné typy vektorů):
head()
- ukáže několik prvních řádků;tail()
- ukáže několik posledních řádků;str
- struktura dat; podobně glimpse()
z
balíčku dplyrhead(USArrests)
#> Murder Assault UrbanPop Rape
#> Alabama 13.2 236 58 21.2
#> Alaska 10.0 263 48 44.5
#> Arizona 8.1 294 80 31.0
#> Arkansas 8.8 190 50 19.5
#> California 9.0 276 91 40.6
#> Colorado 7.9 204 78 38.7
head(USArrests, n = 10)
#> Murder Assault UrbanPop Rape
#> Alabama 13.2 236 58 21.2
#> Alaska 10.0 263 48 44.5
#> Arizona 8.1 294 80 31.0
#> Arkansas 8.8 190 50 19.5
#> California 9.0 276 91 40.6
#> Colorado 7.9 204 78 38.7
#> Connecticut 3.3 110 77 11.1
#> Delaware 5.9 238 72 15.8
#> Florida 15.4 335 80 31.9
#> Georgia 17.4 211 60 25.8
tail(USArrests)
#> Murder Assault UrbanPop Rape
#> Vermont 2.2 48 32 11.2
#> Virginia 8.5 156 63 20.7
#> Washington 4.0 145 73 26.2
#> West Virginia 5.7 81 39 9.3
#> Wisconsin 2.6 53 66 10.8
#> Wyoming 6.8 161 60 15.6
tail(USArrests, n = 15)
#> Murder Assault UrbanPop Rape
#> Oklahoma 6.6 151 68 20.0
#> Oregon 4.9 159 67 29.3
#> Pennsylvania 6.3 106 72 14.9
#> Rhode Island 3.4 174 87 8.3
#> South Carolina 14.4 279 48 22.5
#> South Dakota 3.8 86 45 12.8
#> Tennessee 13.2 188 59 26.9
#> Texas 12.7 201 80 25.5
#> Utah 3.2 120 80 22.9
#> Vermont 2.2 48 32 11.2
#> Virginia 8.5 156 63 20.7
#> Washington 4.0 145 73 26.2
#> West Virginia 5.7 81 39 9.3
#> Wisconsin 2.6 53 66 10.8
#> Wyoming 6.8 161 60 15.6
str(USArrests)
#> 'data.frame': 50 obs. of 4 variables:
#> $ Murder : num 13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
#> $ Assault : int 236 263 294 190 276 204 110 238 335 211 ...
#> $ UrbanPop: int 58 48 80 50 91 78 77 72 80 60 ...
#> $ Rape : num 21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9 25.8 ...
glimpse(USArrests)
#> Rows: 50
#> Columns: 4
#> $ Murder <dbl> 13.2, 10.0, 8.1, 8.8, 9.0, 7.9, 3.3, 5.9, 15.4, 17.4, 5.3, 2.…
#> $ Assault <int> 236, 263, 294, 190, 276, 204, 110, 238, 335, 211, 46, 120, 24…
#> $ UrbanPop <int> 58, 48, 80, 50, 91, 78, 77, 72, 80, 60, 83, 54, 83, 65, 57, 6…
#> $ Rape <dbl> 21.2, 44.5, 31.0, 19.5, 40.6, 38.7, 11.1, 15.8, 31.9, 25.8, 2…
I když to děláme spíš výjimečně, dataframe lze vytvoři přímo v eRku pomocí funkce data.frame()
<- data.frame(
planets name = c("Mercury", "Venus", "Earth", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptune"),
type = c("Terrestrial", "Terrestrial", "Terrestrial","Terrestrial",
"Gas giant", "Gas giant", "Gas giant", "Gas giant"),
diameter = c(0.382, 0.949, 1, 0.532, 11.209, 9.449, 4.007, 3.883),
rotation = c(58.64, -243.02, 1, 1.03, 0.41, 0.43, -0.72, 0.67),
rings = c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE)
)
planets#> name type diameter rotation rings
#> 1 Mercury Terrestrial 0.382 58.64 FALSE
#> 2 Venus Terrestrial 0.949 -243.02 FALSE
#> 3 Earth Terrestrial 1.000 1.00 FALSE
#> 4 Mars Terrestrial 0.532 1.03 FALSE
#> 5 Jupiter Gas giant 11.209 0.41 TRUE
#> 6 Saturn Gas giant 9.449 0.43 TRUE
#> 7 Uranus Gas giant 4.007 -0.72 TRUE
#> 8 Neptune Gas giant 3.883 0.67 TRUE
Výběr prvků dataframu je velmi podobný tomu u matic.
# První až třetí řádek, první sloupec
1:3, 1]
planets[#> [1] "Mercury" "Venus" "Earth"
# První a třetí sloupec
c(1, 3)]
planets[, #> name diameter
#> 1 Mercury 0.382
#> 2 Venus 0.949
#> 3 Earth 1.000
#> 4 Mars 0.532
#> 5 Jupiter 11.209
#> 6 Saturn 9.449
#> 7 Uranus 4.007
#> 8 Neptune 3.883
# Jde to i bez čárky, protože sloupce jsou považovány za základní
# stavební prvky dataframu
c(1, 3)]
planets[#> name diameter
#> 1 Mercury 0.382
#> 2 Venus 0.949
#> 3 Earth 1.000
#> 4 Mars 0.532
#> 5 Jupiter 11.209
#> 6 Saturn 9.449
#> 7 Uranus 4.007
#> 8 Neptune 3.883
length(planets) # Proto i délka odpovídá počtu sloupců
#> [1] 5
# První až třet řádek, sloupec "name"
1:3,"name"]
planets[#> [1] "Mercury" "Venus" "Earth"
Sloupce můžeme z dataframu “vyříznout” podobně jako u listů.
"name"]]
planets[[#> [1] "Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus"
#> [8] "Neptune"
$name
planets#> [1] "Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus"
#> [8] "Neptune"
$diameter
planets#> [1] 0.382 0.949 1.000 0.532 11.209 9.449 4.007 3.883
K seřezaní řádků podle hodnot některého ze sloupců můžeme funkci order(). Výstupem této funkce je pořadí hodnot podle daného vektoru nebo vektorů
$diameter
planets#> [1] 0.382 0.949 1.000 0.532 11.209 9.449 4.007 3.883
order(planets$diameter) # Defaultně vzestupně
#> [1] 1 4 2 3 8 7 6 5
order(planets$diameter, decreasing = TRUE) # Takto sestupně
#> [1] 5 6 7 8 3 2 4 1
# Vektor, který je výstupem funkce order(), můžeme využít k seřazení řádků
order(planets$diameter, decreasing = FALSE), ]
planets[#> name type diameter rotation rings
#> 1 Mercury Terrestrial 0.382 58.64 FALSE
#> 4 Mars Terrestrial 0.532 1.03 FALSE
#> 2 Venus Terrestrial 0.949 -243.02 FALSE
#> 3 Earth Terrestrial 1.000 1.00 FALSE
#> 8 Neptune Gas giant 3.883 0.67 TRUE
#> 7 Uranus Gas giant 4.007 -0.72 TRUE
#> 6 Saturn Gas giant 9.449 0.43 TRUE
#> 5 Jupiter Gas giant 11.209 0.41 TRUE
order(planets$diameter, decreasing = TRUE), ]
planets[#> name type diameter rotation rings
#> 5 Jupiter Gas giant 11.209 0.41 TRUE
#> 6 Saturn Gas giant 9.449 0.43 TRUE
#> 7 Uranus Gas giant 4.007 -0.72 TRUE
#> 8 Neptune Gas giant 3.883 0.67 TRUE
#> 3 Earth Terrestrial 1.000 1.00 FALSE
#> 2 Venus Terrestrial 0.949 -243.02 FALSE
#> 4 Mars Terrestrial 0.532 1.03 FALSE
#> 1 Mercury Terrestrial 0.382 58.64 FALSE
# Co dělá tato funkce?
sort(planets$diameter)
#> [1] 0.382 0.532 0.949 1.000 3.883 4.007 9.449 11.209
sort(planets$diameter, decreasing = TRUE)
#> [1] 11.209 9.449 4.007 3.883 1.000 0.949 0.532 0.382
K filtrování můžeme použít logické operátory v kombinaci s hranatými závorkami nebo funkcí subset(). Funkce subset() vyřaduje o něco méně psaní, protože vektor/sloupec hledá automaticky v rámci použitého dataframu.
$rotation < 0
planets#> [1] FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE
# Tyto operace jsou ekvivalentní:
$rotation < 0, ]
planets[planets#> name type diameter rotation rings
#> 2 Venus Terrestrial 0.949 -243.02 FALSE
#> 7 Uranus Gas giant 4.007 -0.72 TRUE
subset(planets, rotation < 0)
#> name type diameter rotation rings
#> 2 Venus Terrestrial 0.949 -243.02 FALSE
#> 7 Uranus Gas giant 4.007 -0.72 TRUE
Brzo se naučíme ještě jednoduší a intuitivnější funkce (z balíčku tidyverse) pro výběr řádků a sloupců.
Tibbles jsou vlastně upgradované dataframes. Chovájí se trochu jinak
než obyčejné dataframes, ale tak, aby nám to ulehčilo práci. Obyčejný
dataframe můžeme změnit v tibble pomocí funkce as_tibble()
a ověřit si, zda je nějaký objekt tibble, pomocí funkce
is_tibble
.
head(iris)
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1 5.1 3.5 1.4 0.2 setosa
#> 2 4.9 3.0 1.4 0.2 setosa
#> 3 4.7 3.2 1.3 0.2 setosa
#> 4 4.6 3.1 1.5 0.2 setosa
#> 5 5.0 3.6 1.4 0.2 setosa
#> 6 5.4 3.9 1.7 0.4 setosa
is_tibble(iris)
#> [1] FALSE
as_tibble(iris)
#> # A tibble: 150 × 5
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> <dbl> <dbl> <dbl> <dbl> <fct>
#> 1 5.1 3.5 1.4 0.2 setosa
#> 2 4.9 3 1.4 0.2 setosa
#> 3 4.7 3.2 1.3 0.2 setosa
#> 4 4.6 3.1 1.5 0.2 setosa
#> 5 5 3.6 1.4 0.2 setosa
#> 6 5.4 3.9 1.7 0.4 setosa
#> 7 4.6 3.4 1.4 0.3 setosa
#> 8 5 3.4 1.5 0.2 setosa
#> 9 4.4 2.9 1.4 0.2 setosa
#> 10 4.9 3.1 1.5 0.1 setosa
#> # … with 140 more rows
Vytvořit tibble z jednotlivých vektorů pak lze pomocí funkce tibble(). Tato funkce automaticky recykluje vektory, které mají jen jeden prvek, a umožňuje se rovnou odkazovat na právě vytvořené vektory, jako je to ilustrováno níže.
tibble(
x = 1:5,
y = 1,
z = x ^ 2 + y
)#> # A tibble: 5 × 3
#> x y z
#> <int> <dbl> <dbl>
#> 1 1 1 2
#> 2 2 1 5
#> 3 3 1 10
#> 4 4 1 17
#> 5 5 1 26
Tibble také umožňuje dát sloupcům nestandardní jména, např. jména nezačínající písmenem nebo zahrnující speciální znaky. Stačí k tomu použít zpětný apostrof (R Alt + ý). Ale není to něco, co bychom si v praxi přáli dělat.
<- tibble(
tb `:)` = "smile",
` ` = "space",
`2000` = "number"
)
tb#> # A tibble: 1 × 3
#> `:)` ` ` `2000`
#> <chr> <chr> <chr>
#> 1 smile space number
Další způsob, jak vytvořit tibble, nabízí funkce tribble(). S využitím této funkce “plníme” tibble po řádcích, nikoli po sloupcích jako. Jména sloupců uvádíme jako první a dáváme před ně tildu (na české klávesnic R Alt + 1)
tribble(
~x, ~y, ~z, # Jména sloupců
"a", 2, 3.6, # první řádek hodnot
"b", 1, 8.5 # druhý řádek hodnot
)#> # A tibble: 2 × 3
#> x y z
#> <chr> <dbl> <dbl>
#> 1 a 2 3.6
#> 2 b 1 8.5
Když si tibble vyvoláme do konzole, na rozdíl od obyčejných dataframes ji nezahltí, protože zobrazí jen prvních deset řádků a tolik sloupců, kolik se jich do konzole vleze. Navíc se u každého sloupce zobrazí jeho typ.
<- tibble(
tb a = Sys.time() + runif(1e3) * 86400,
b = as.Date(Sys.time()) + runif(1e3) * 30,
c = 1:1e3,
d = runif(1e3),
e = sample(letters, 1e3, replace = TRUE)
)
tb#> # A tibble: 1,000 × 5
#> a b c d e
#> <dttm> <date> <int> <dbl> <chr>
#> 1 2022-09-19 14:13:42 2022-09-30 1 0.153 u
#> 2 2022-09-19 03:31:15 2022-09-30 2 0.449 k
#> 3 2022-09-19 19:50:11 2022-10-07 3 0.186 n
#> 4 2022-09-19 17:01:36 2022-10-15 4 0.427 e
#> 5 2022-09-19 15:08:52 2022-09-24 5 0.821 k
#> 6 2022-09-19 13:56:29 2022-10-04 6 0.0504 w
#> 7 2022-09-19 08:02:34 2022-10-09 7 0.325 e
#> 8 2022-09-19 11:49:30 2022-09-29 8 0.842 x
#> 9 2022-09-19 20:06:05 2022-09-20 9 0.0402 v
#> 10 2022-09-19 13:04:16 2022-10-07 10 0.792 a
#> # … with 990 more rows
Kdybychom nám toto nevyhovovalo, můžeme pomocí funkce print upřesnit, kolik řádků a sloupců chceme v konzoli zobrazit.
print(tb, n = 20, width = Inf)
#> # A tibble: 1,000 × 5
#> a b c d e
#> <dttm> <date> <int> <dbl> <chr>
#> 1 2022-09-19 14:13:42 2022-09-30 1 0.153 u
#> 2 2022-09-19 03:31:15 2022-09-30 2 0.449 k
#> 3 2022-09-19 19:50:11 2022-10-07 3 0.186 n
#> 4 2022-09-19 17:01:36 2022-10-15 4 0.427 e
#> 5 2022-09-19 15:08:52 2022-09-24 5 0.821 k
#> 6 2022-09-19 13:56:29 2022-10-04 6 0.0504 w
#> 7 2022-09-19 08:02:34 2022-10-09 7 0.325 e
#> 8 2022-09-19 11:49:30 2022-09-29 8 0.842 x
#> 9 2022-09-19 20:06:05 2022-09-20 9 0.0402 v
#> 10 2022-09-19 13:04:16 2022-10-07 10 0.792 a
#> 11 2022-09-19 19:15:48 2022-09-18 11 0.962 v
#> 12 2022-09-19 06:36:28 2022-09-24 12 0.661 b
#> 13 2022-09-19 16:06:29 2022-10-08 13 0.00872 d
#> 14 2022-09-19 05:28:10 2022-10-13 14 0.466 f
#> 15 2022-09-19 13:22:24 2022-10-11 15 0.717 e
#> 16 2022-09-19 10:39:36 2022-09-22 16 0.0282 s
#> 17 2022-09-19 05:28:11 2022-09-29 17 0.845 l
#> 18 2022-09-19 12:39:33 2022-10-11 18 0.746 a
#> 19 2022-09-19 21:01:32 2022-10-08 19 0.264 j
#> 20 2022-09-19 20:45:14 2022-10-05 20 0.746 d
#> # … with 980 more rows
Výběr prvků z tibblu je v podstatě stejný jako výběr prvků z dataframes, protože tibble je “jen” vylepšený dataframe.
<- tibble(
df x = runif(5),
y = rnorm(5),
z = runif(5)
)
df#> # A tibble: 5 × 3
#> x y z
#> <dbl> <dbl> <dbl>
#> 1 0.699 0.665 0.651
#> 2 0.900 -0.565 0.761
#> 3 0.723 -0.962 0.281
#> 4 0.255 0.623 0.984
#> 5 0.309 0.106 0.964
# Výběr jediného prvku pomocí jména
$x
df#> [1] 0.6986846 0.8999534 0.7232587 0.2550500 0.3086717
"x"]]
df[[#> [1] 0.6986846 0.8999534 0.7232587 0.2550500 0.3086717
# Výběr prvků pomocí pozice
1]]
df[[#> [1] 0.6986846 0.8999534 0.7232587 0.2550500 0.3086717
1]
df[#> # A tibble: 5 × 1
#> x
#> <dbl>
#> 1 0.699
#> 2 0.900
#> 3 0.723
#> 4 0.255
#> 5 0.309
mtcars
.<- data.frame(
df x = c(1, 2, 3),
y = c("a", "b", "c")
)
$x
df#> [1] 1 2 3
"y"]
df[, #> [1] "a" "b" "c"
c("x", "y")]
df[, #> x y
#> 1 1 a
#> 2 2 b
#> 3 3 c
<- tibble(
tb x = c(1, 2, 3),
y = c("a", "b", "c")
)
$x
tb#> [1] 1 2 3
"y"]
tb[, #> # A tibble: 3 × 1
#> y
#> <chr>
#> 1 a
#> 2 b
#> 3 c
c("x", "y")]
tb[, #> # A tibble: 3 × 2
#> x y
#> <dbl> <chr>
#> 1 1 a
#> 2 2 b
#> 3 3 c
is_
nebo
is.
) a jak se používají.typeof()
,
is.na()
, sum()
, mean()
,
rowSums()
, colSums()
, rowMeans()
,
colMeans()
, head()
, tail()
,
str()
, glimpse()
, factor()
,
subset()
, order()
, sort()
.