4  Opakovaní R

Cíle cvičení
  • Umět vyhledat nápovědu k funkci.
  • Ovládat základní matematické výpočty pmocí funkcí a operátorů.
  • Umět definovat objekt v datovém typy a struktuře a tyto vzájemně transoformovat.
  • Ovládat běh výpočtu pomocí podmínek a cyků.
  • Přidávat k pracovnímu postupu vlastní funkce.

Základy jazyka jsou vyučovány již v prvním semestru studia Vodního hospodářství. Na tomto místě je pouze zhuštěný přehled funkcionality z uvedeného kurzu.

4.1 Nápověda

Zadává se do konzole ve tvaru help(<jméno funkce>), nebo <jméno funkce>. Pokud bychom se chtěli podívat přímo do kódu funkce, také je to možné, jméno funkce pouze vepíšeme do konzole bez závorek, případně použijeme příkazu View(<jméno funkce>). Kromě toho existuje v R také help.search(<jméno funkce>) pod zkratkou ??, jež hledá fulltextovou nápovědu napříč nainstalovanými balíčky. Dále je ještě možné prohledat mailing list jazyka R pomocí funkce RSiteSearch(), která otevře nové okno předdefinovaného prohlížeče. Dále jsou velmi užitečné tematicky ucelené karty nápověd: ?Logical, ?Constants, ?Control, ?Arithmetic, ?Syntax, ?Special a další.

Úloha
  1. Vyhledejte nápovědu k DateTimeClasses.
    1. Co reprezentují třídy POSIXct a POSIXlt? Jaký je mezi nimi rozdíl?
    2. V nápovědě k funkci min najděte a spustťte příklady užití.
    3. Nalezněte funkci pro výpočet \(5!\).

4.2 Jmenné konvence

Objekty, které vznikají při práci s R musí splňovat následující jmenné konvence.

  • Název objektu nelze začínat číslovkou nebo operátorem,
  • nesmít být totožný s žádným klíčovým slovem,
  • ani obsahovat mezeru.
Klíčová slova

Klíčová slova jsou rezervována pro správnou funkci interpretru jazyka. Pokus o Jejich přepis vyvolá chybovou hlášku. Vyzkoušejte například zápisem TRUE <- 1.

if, else, repeat, while, function, for, in, next, repeat, break, TRUE, FALSE, NULL, Inf, NaN, NA, NA_integer_, NA_real_, NA_complex_, NA_character_, a speciální znak: _

Nedoporučuje se vkládat do názvu proměnné tečku, např. morava.prutoky, a pojmenovávat shodně s běžně používanou funkcí. R je case-sensitive jazyk tzn., že proměnná X není ekvivalentní s proměnnou x.

Úloha
  1. Intuitivně by nás mohlo vést nahrát data do proměnné data. Je to chybný postup, neboť data() je funkce zpřístupňující různé datové sady, například ty, které jsou běžnou součástí instalace (v balíčku datasets). Vyzkoušejte s pomocí nápovědy library(help = datasets).
Příklady nevhodných proměnných

aaa, Morávka průtok [m/s], moje.proměnná
Všechny tyto názvy proměnných jsou tzv. validní, nicméně žádný není vhodný.

4.3 Uvozovky a závorky

Představují párové znaky jazyka R. Závorky se používají trojího typu: kulaté, hranaté a složené a všechny mají jasně vymezné pole působnosti.

  • Kromě matematického zápisu () se používají vždy se jménem funkce a uvozují prostor ve kterém se specifikují parametry funkce.
  • [] se vždy pojí se jménem objektu (vektoru, pole, listu, …) a vymezují výběr z daného objektu,
  • {} ohraničují blok kódu, který se má celý vykonat (sekvenčně).

Uvozovky uvozují textové řetězce. Lze používat jak dvojté " tak jednoduché ' uvozovky zcela zástupně, je pouze třeba uzavírat shodným typem. Hojně se lze setkat se zpětnými uvozovkami, které se například použijí pro ohraničení nestandardního názvu sloupce ve struktuře.

Kód
"Správně"
"Špatně'
Úloha
  1. Zadejte špatnou variantu z kódu výše do konzole a sledujte chování prostředí. Co vyjadřuje znak +?
  2. Pomocí funkce cat() se pokuste vypsat na konzoli tento text:  Říkám: “Mám rád R!”.

4.4 Operátory

Rozlišujeme operátory aritmetické, relační, přiřazení a patří sem i množinové funkce.

Znak Význam
+ , - , * , / , %% , %/% , ** nebo ^, %*% aritmetické operátory (sčítání, odčítání, násobení, dělení, modulo, celočíselné dělení, mocnění a maticové násobení)
> ,>= , < , <= , == , != relační operátory (větší/menžší než, rovno, nerovno)
! , & , && , | , || logické (ne, a soužasně, zdvojené po prvcích vektoru)
~ zadání funkčního vztahu
<- , =, <<-, -> operátory přiřazení
$ jmenný index v heterogenních strukturách
: rozsah
isTRUE() , all() , any() , %in% , setdiff() množinové funkce
Kód

xor(x)
isTRUE(x)
any()
all()
%in%
setdiff(x, y)
11
Negace
12
Je \(x\) “pravda”?
13
Je něco z obsahu “pravda”?
14
Je vše z obsahu “pravda”?
15
Je něco obsaženo v?
16
Chybí něco něco z obsahu v?
Úloha
  1. Použite k výpočtu operátory či množinové funkce:
    1. Zjistěte, zda je číslo 1109388 dělitelné 7.
    2. Do vektoru \(\mathbf{\mathrm{a}}\) uložte násobky 3 v rozsahu \(\langle-121;30\rangle\) a \(\mathbf{\mathrm{b}}\) násobky 7 v rozmezí
    3. Vypište hodnoty

4.5 Matematické funkce

Funkce Význam
log(x) logaritmus \(x\) o základu \(e\)
exp(x) odlogaritmování \(x(e^x)\)
log(x, n) logaritmus \(x\) o základu \(n\)
log10(x) logaritmus \(x\) o základu \(10\)
sqrt(x) druhá odmocnina z \(x\)
factorial(x) \(x!\)
choose(n, x) binomické koeficienty \[ \binom{n}{k} = \frac{n!}{k!(n-k)!} \]
ceiling(x) nejmenší celé číslo větší než \(x\)
floor(x) největší celé číslo před \(x\)
trunc(x) nejbliřší celé číslo mez i\(x\) a 0
round(x, digits) zaokrouhlení \(x\) na \(n\) desetinných míst
signif(x, digits) zaokrouhlení na počet platných číslic
cos(x) , sin(x) , tan(x) funkce kosinus, sinus, tangens v radianech
acos(x) , asin(x) , atan(x) inverzní trigonometrické funkce
abs(x) absolutní hodnota
Úloha
  1. Vyhodnoťte s pomocí R následující výrazy:
    1. \(1 + 3 \cdot (2 / 3)\:\mathrm{mod}\:3=\)
    2. \(\dfrac{\sin(2.3)}{\cos(\pi)}=\)
    3. \(\sum\limits_{i = 1}^{53}i=\)
    4. \(\dfrac{-\infty}{0}=\) , \(\dfrac{-\infty}{\infty}=\) , \(\dfrac{0}{0}=\)
    5. \(\left(\dfrac{2}{35}\right)^{0.5} \cdot 3 \cdot (2 / 3)=\)
    6. \(20!=\)
    7. \(\int_{0}^{3\pi} \sin(x) dx=\)
    8. \(\sqrt[3]{561}=\)
    9. \(\mathrm{diag}\left( \pmatrix{5\\ 3}\cdot \pmatrix{6 & 5}\right)=\)
    10. \(y=x^2 + \sqrt[3]{x};\:y^\prime=\)

4.6 Datové typy

Tvoří prvky struktur. R je dynamicky typovaný jazyk, nepožaduje před zavedením proměnné její deklaraci.

Základní datové typy a nucené převody mezi nimi.
logical integer numeric complex character
logical logical integer numeric complex character
integer logical integer numeric complex character
numeric logical numeric numeric complex character
complex logical integer + warning numeric + warning complex character
character NA_logical NA_integer + warning NA_numeric + warning NA_complex + warning character

K datovým typům (třídám) se pojí funkce is.___ a as.___ kteří slouží k dotazování na typ, resp. jeho nucenou změnu a dále funkce class(), mode() .

Kód
is.character("ABC")
[1] TRUE
Kód
as.integer(11 + 1i)
Warning: imaginary parts discarded in coercion
[1] 11

Chybějící záznamy a speciální numerické případy NA, NaN, NULL, Inf, -Inf jsou hodnoty, které mohou vzniknout například jako výsledek početního úkonu, nebo špatného importu dat. Výraz NA je tvořen v datovém typu logical, nejméně náročném na paměť. Jinak je možné specifikovat chybějící hodnotu ve všech ostatních datových typech NA_real_ (odpovídá double), NA_integer_, NA_complex_ a NA_character_, které je vhodné využít zejména při vytváření datového rámce s přesně zadaným typem sloupců. NULL je návratová hodnota mnoha funkcí a výrazů, reprezentuje prázdný objekt. Výsledky NaN a ±Inf pochází z aritmetických operací \(\dfrac{1}{0}\) resp. \(\dfrac{\pm0}{1}\) . na.omit(), is.na(), complete.cases().

4.7 Základní datové struktury

Základní datové struktury rozlišujeme na atomické (homogenní) a heterogenní datové struktury.

4.7.1 Homogenní datové struktury

Homogenní datové struktury obsahují atomické vektory, faktory, matice a pole. Název je odvozen od jejich omezení v podvýběru obsahovat pouze typ sebe sama tzn. podvýběr matice může být opět pouze matice.

4.7.1.1 Atomický vektor vector

Vektor je v jazyce R základní stavební strukturou, nic jako skalární veličina zde není. Koncept vektoru je zde chápán v matematickém smyslu jako jednosloupcová matice \(\boldsymbol{\mathrm{A}} = (a_{ij})_{m1}\) hodnot.

\[ \mathbf{\mathrm{u}} = \begin{pmatrix} 1\\ 1.5\\ -14\\ 7.223\\ \end{pmatrix}, \qquad \mathbf{\mathrm{v}} = \begin{pmatrix} \mathrm{TRUE}\\ \mathrm{FALSE}\\ \mathrm{TRUE}\\ \mathrm{TRUE}\\ \end{pmatrix}, \qquad \mathbf{\mathrm{u^T}} = \begin{pmatrix} 1 & 1.5 & -14 & 7.233\\ \end{pmatrix} \]

Může nabývat jakéhokoliv datového typu, nicméně všechny prvky v daném vektoru jsou právě jednoho typu, čímž rozumíme, že je tato struktura tzv. homogenní. Vektor je možné vytvořit mnoha způsoby, mezi nejčastější patří funkce vector(mode = "numeric", length = 10) a funkce c(), případně vzniká pomocí opetárorů [ nebo [[.

S vektory se pojí důležité pravidlo - recyklace hodnot.

Kód
v <- c(1.4, 2.0, 6.1, 2.7)
u <- c(2.0, 1.3)
u + v
u * v
u * 2.3
1
Sčítám vektory přičemž délka jednoho je násobkem délky druhého.
2
Násobím vektory přičemž délka jednoho je násobkem délky druhého.
3
Násobení vektoru číslenou hodnotou
[1] 3.4 3.3 8.1 4.0
[1]  2.80  2.60 12.20  3.51
[1] 4.60 2.99
Práce s vektory
Kód
x <- 1:10
x <- seq(10:1)
x <- vector(mode = "numeric", length = 10)
x <- replicate(n = 10, expr = eval(2))
x <- sample(x = 10, size = 10, replace = TRUE)
x <- rep(x = 15, times = 2)
x <- rnorm(n = 10, mean = 2, sd = 20)
t(x) * x
names(x) <- LETTERS[1:length(x)]
x[x > 0]
x[1:3]
1
Tvorba vektoru \(\boldsymbol{\mathrm{x}}\) různými úkony. Použití sekvence, repetice, opakování a vzorkování.
2
Transpozice vektoru.
3
Pojmenování pozic ve vektoru
4
Výběr hodnot z vektoru na základě podmínky
5
Výběr hodnot z vektoru na základě pozice
         [,1]     [,2]     [,3]     [,4]     [,5]    [,6]     [,7]     [,8]
[1,] 386.7648 1457.213 52.01813 584.0477 62.82809 83.4891 27.89627 70.74835
         [,9]    [,10]
[1,] 448.9558 264.7829
        A         B         D         E         F         I         J 
19.666337 38.173463 24.167079  7.926417  9.137237 21.188577 16.272151 
        A         B         C 
19.666337 38.173463 -7.212359 
Úloha
    1. Vytvořte libovolným způsobem vektor x 10 různých číselných hodnot, kde \(x\in\mathbb{R}\).
    2. Zapište výraz pro výběr čísel v rozmezí -5 a 5 z tohoto vektoru.
    3. Proveďte převod na celočíselný typ a diskutujte výsledek.
    4. Přidejte k vektoru 3 pozice “A”, “B” a “C”, změnil se vektor?

4.7.1.2 Faktor

Faktorem rozumíme kategorickou proměnnou, která je určena výčtem hodnot. Ukážeme si na příkladu “tříd přesnosti měření”.

Kód
trida <- factor(x = 1:4,
                labels = c(paste(1:4, ". třída", sep = "")), 
                ordered = TRUE)

4.7.1.3 Matice matrix

Rozšířením rozměrů vektoru vznikne matice nebo obecně pole.

Kód
x <- c(1:10)
dim(x) <- c(2, 5)
x
1
Převod na rozměr \(2\times 2\)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
Funkce Úkon
nrow(), ncol() počet řádků, sloupců matice
dim() řádky \(\times\) sloupce matice
det() deteminant matice
eigen() vlastní čísla a vlastní vektory matice
colnames() jména sloupců v matici
rowSums() řádkové součty matice
colMeans() sloupcové průměry matice
M[m, ] Výběr \(m\)-tého řádku matice
M[ ,n] Výběr \(n\)-tého sloupce matice

Stejně jako u vektoru opět platí typová homogenita

Kód
B <- matrix(
  data = c(1, 2 + 3i, 5.4, 4, 5), 
  nrow = 2, 
  ncol = 3)
Warning in matrix(data = c(1, 2 + (0+3i), 5.4, 4, 5), nrow = 2, ncol = 3): data
length [5] is not a sub-multiple or multiple of the number of rows [2]
Kód
A <- matrix(data = seq(from = 1, to = 16, by = 2), nrow = 4)
str(A)
dim(A)
svd(A)
diag(A)
# sweep(x = A, MARGIN = 1, STATS = mean)
##  num [1:4, 1:2] 1 3 5 7 9 11 13 15
## [1] 4 2
## $d
## [1] 25.930394  2.759471
## 
## $u
##            [,1]       [,2]
## [1,] -0.3396065 -0.7646355
## [2,] -0.4383147 -0.3284512
## [3,] -0.5370229  0.1077330
## [4,] -0.6357311  0.5439173
## 
## $v
##            [,1]       [,2]
## [1,] -0.3389761  0.9407950
## [2,] -0.9407950 -0.3389761
## 
## [1]  1 11
1
Struktura objektu
2
Dimenze matice
3
Singulární rozklad
4
Prvky na diagonále matice
Úloha
    1. S pomocí nápovědy k funkci rnorm() vytvořte matici \(\boldsymbol{\mathrm{M}}; h(\boldsymbol{\mathrm{M}}) = 8\) náhodných čísel.
    2. Vytvořte vektor hodnot od \(100\) do \(1\) sestupně, využijte nápovědu k funkci seq().
    3. Spočtěte rozdíl, matic \(\boldsymbol{\mathrm{A}}\), \(\boldsymbol{\mathrm{B}}\). \[\boldsymbol{\mathrm{A}} = \left( \begin{matrix} 2 & 2 & 5\\ 9 & 2 & 7\\ 1 & 3 & 18\\ \end{matrix} \right),\qquad \boldsymbol{\mathrm{B}} = \left( \begin{matrix} 5 & 4 & 5\\ -7 & 2 & 4\\ 10 & 1 & 5\\ \end{matrix} \right) \]
    4. Spočítejte inverzní matici k matici \(\boldsymbol{\mathrm{A}}\). Najděte vhodnou funkci s pomocí nápovědy.
    5. S pomocí hodnot TRUE/FALSE vytvořte matici \(\boldsymbol{\mathrm{M}}(3,3)\), změňte typ prvku na pozici \(\boldsymbol{\mathrm{M}}[1, 1]\) na textový řetězec. Ovlivní tato změna ostatní prvky v matici?
    6. Vyřešte s pomocí funkce solve() soustavu lineárních rovnic: \[\begin{array} -3x & +2y& +z&=1\\ -2x & -y& +z&=2\\ 2x & +y& -4z&=0 \end{array} \]

4.7.2 Heterogenní datové struktury

Za rúznorodé struktury se označují ty, které mohou uchovávat dva a více prvků rozdílného typu současně. Z těch základních to jsou data.frame a list, dále pak S4, nebo R6 třídy, případně další uživatelem vytvořené struktury.

4.7.2.1 Datová tabulka data.frame

data.frame je de facto vektor stejně dlouhých vektorů, které kromě toho, že musí být shodné délky, mohou být vzájmeně rozdílného datového typu.

Kód
DF <- data.frame(name = letters[1:5], 
                 value = rnorm(5))
DF
##   name      value
## 1    a -0.2071337
## 2    b  0.3253010
## 3    c -0.4467706
## 4    d  0.5647221
## 5    e  0.9838482
DF["name"]        # podvýběr do data.frame
##   name
## 1    a
## 2    b
## 3    c
## 4    d
## 5    e
DF[["name"]]      # podvýběr do vektoru
## [1] "a" "b" "c" "d" "e"
DF[, "name"]      # podvýběr do vektoru
## [1] "a" "b" "c" "d" "e"

Práce uvnitř data.frame

Kód
DF <- data.frame(
  mon = rep(month.abb, 
            times = c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)), 
  value = rnorm(365), 
  yr = 2001)
str(DF)
## 'data.frame':    365 obs. of  3 variables:
##  $ mon  : chr  "Jan" "Jan" "Jan" "Jan" ...
##  $ value: num  -0.546 0.641 0.124 0.887 -1.284 ...
##  $ yr   : num  2001 2001 2001 2001 2001 ...
names(DF)
## [1] "mon"   "value" "yr"
nrow(DF)
## [1] 365
ncol(DF)
## [1] 3

4.8 Řídící struktury

Směrují běh programu, tvoří základní stavební prvky algoritmů. Mezi řídící strukury řadíme podmínky a cykly. Mohli bychom přidat i složené závorky, neboť pro struktury uvozují bloky kódu.

4.8.1 Podmínky

Podmínkami vytváříme v kódu větvení.

4.8.1.1 if()

Kód
A <- 1
if(A >= 1) {
  cat("A je větší nebo shodné s 1.")
}
A je větší nebo shodné s 1.
Kód
A <- 5
if(A >= 2) {
  cat("A je větší nebo shodné s 2.")
} else if(A > 2) {
  cat("A je větší než 2.")
}
1
Řetěz podmínek se uzavře v momentě, kdy je výraz v závorce poprvé vyhodnocen jako pravdivý.
A je větší nebo shodné s 2.

4.8.1.2 ifelse()

Vektorizovaný tvar podmínky, který lze volat přes prvky struktur.

Kód
x <- -5:5
cat("Prvek x + 3 je více než 0: ", ifelse(x - 3 > 0, yes = "Ano", no = "Ne"))
Prvek x + 3 je více než 0:  Ne Ne Ne Ne Ne Ne Ne Ne Ne Ano Ano

Hojně používaný například při tvorbě nových sloupců uvnitř data.frame.

Kód
random_data <- data.frame(
  date = seq(from = as.Date("2025-01-01"), to = as.Date("2025-12-31"), by = "1 day")
)
random_data$h_year <- ifelse(test = format(random_data$date, "%m") > 10, 
                             yes = 2026, 
                             no = 2025)
rbind(
  head(random_data, 3),
  tail(random_data, 3)
)
          date h_year
1   2025-01-01   2025
2   2025-01-02   2025
3   2025-01-03   2025
363 2025-12-29   2026
364 2025-12-30   2026
365 2025-12-31   2026

4.8.1.3 switch()

Konstrukcí switch vytváříme větvení na základě stavu objektu. K jednotlivým stavům, kterých může nebýt, přiřazujeme větve (bloky kódu), které se mají vykonat.

Kód
varianta <- "B"
2 * switch(
      varianta,
        "A" = 2,
        "B" = 3)
1
Varianta “A nenastala,
2
nastala varianta “B”, tzn. výraz je vyhodnocen ve tvaru \(2\cdot 3 = 6\)
[1] 6
Úloha
    1. Vytvořte s pomocí podmínek známkovací schéma:
Známka Rozmezí
1 90 - 100 %
2 75 - 89 %
3 60 - 74 %
4 < 60 %

4.8.2 Cykly

Zajištují, že se část kódu provede opakovaně.

4.8.2.1 for() z definovaného rozsahu

Pokud je předem znám počet opakování cyklu (nebo je jinak implicitně určen), lze použít for cyklu.

Kód
for(i in 1:4) {
  cat("Iterace: ", i, "\n")
}
Iterace:  1 
Iterace:  2 
Iterace:  3 
Iterace:  4 

4.8.2.2 while() s pomocí podmínky

V případech, kdy počet opakování není předem znám, ale je známa podmínka, za které cyklus má probíhat.

Kód
i <- 1
while(i < 5) {
  cat("Iterace: ", i, "\n")
  i <- i + 1
}
Iterace:  1 
Iterace:  2 
Iterace:  3 
Iterace:  4 

4.8.2.3 repeat s únikovou sekvencí

Počet opakování není znám. Nicméně lze definovat případ, kdy má cyklus skončit.

Kód
i <- 1
repeat {
  cat("Iterace: ", i, "\n")
  i <- i + 1
  if(i >= 5) break #<1>
}
1
Prováděj
2
Vnořenou podmínkou následovanou klíčovým slovem break definujeme konec cyklu.
Iterace:  1 
Iterace:  2 
Iterace:  3 
Iterace:  4 

Kromě únikového klíčového slova break po němž cyklus okamžitě skončí je k využití příkaz next, po němž se zbytek příkazů v dané iteraci přeskočí a operátor %||%. Je dobré si uvědomit, že cyklus typu while se nemusí provést ani jednou, k čemuž dojde, když výsledkem prvního vyhodnocení podmínky je FALSE. Což právě použití repeat ošetřuje.

Úloha
    1. Vytvořte cyklus, který pro čísla \(1, 2, 3, 4, 5\) vypíše jejich třetí mocniny
    2. Pro stejná čísla provede kumulativní součet.
    3. Pro číslo n provede výpočet faktorialu.
    4. S pomocí funkce readline() od uživatele požaduje číslo, které vždy vypíše. Pokud je číslo záporné, skončí smyčku.

4.9 Vlastní funkce

K funkce slouží klíčové slovo function, které v závorkách doprovází argumenty sloužící k vnitřní specifikaci funkce.

Kód
x <- rnorm(100)
nejblizsi_hodnota <- function(x, value) {
  x[which(abs(x - value) == min(abs(x - value)))]
}

cat("Hodnota nejblíže 0 z vektoru x je:" , 
    nejblizsi_hodnota(x = x, value = 0))
1
Příklad funkce, která vyhledá nejbližší z hodnot vektoru x k referenční hodnotě value.
Hodnota nejblíže 0 z vektoru x je: 0.01265622

4.10 Rekapitulace

Úloha

Vyplňte následující formulář bez použití R.

  1. Zvolte platné tvrzení pro data.frame:
  2. Matici je možné vytvořit z vektoru přidáním dimenze:
  3. Co je výsledkem výrazu: \(\sin(\frac{0}{0})\)
  4. Vyberte, platné tvrzení pro datovou strukturu list:
  5. Napište výraz pro nepřiřazenou celočíselnou hodnotu :
  6. Dolňte chybějící zápis cyklu:
  for(i in 1:5) {
    cat(___)    
  }
  > 54321
  1. Vytvořte funkci FD0(x) s parameterm x, který bude reprezentovat teplotu. Funkce FD0(x) bude vracet počet hodnot nižších než 0.