3  Základní datové typy

Každá hodnota uložená v proměnné má nějaký datový typ. Abyste porozuměli chování R, musíte se s vlastnostmi a možnostmi jednotlivých datových typů seznámit.

V této kapitole se naučíte

3.1 Základní datové typy

Data se skládají z jednotlivých hodnot. Každá taková hodnota má určitý datový typ. V R existuje mnoho základních typů dat. Pro datovou analýzu se však hodí především následující čtyři datové typy:

  • logical může obsahovat jen dvě logické hodnoty: TRUE (“pravda”) a FALSE (“nepravda”). Tyto hodnoty je možné zkrátit na T a F, ale výrazně se to nedoporučuje, protože zkrácená jména T a F je možné předefinovat, po čemž by původně funkční kód dělal nepředvídatelné věci.
  • integer může obsahovat kladná i záporná celá čísla. Pokud je chcete zadat, musíte za číslo napsal L, tj. např. 1L.
  • double může obsahovat kladná i záporná reálná čísla. Když zadáte v konzoli nebo skriptu číslo bez příznaku L, bude v paměti reprezentované jako double, i když to bude shodou okolností celé číslo. V konzoli však R vypíše celá čísla inteligentně bez desetinných míst, i když jsou uložená v proměnné typu double.
  • character může obsahovat libovolný řetězec (text). V R se řetězce zadávají mezi dvěma uvozovkami nebo apostrofy. Uvozovky a apostrofy nelze kombinovat, tj. nejde jeden řetězec uvést uvozovkou a ukončit apostrofem. To umožňuje zadat apostrofy nebo uvozovky jako součást řetězce tak, že je např. řetězec uvozen i ukončen uvozovkami a uvnitř řetězce je použit apostrof. Jinou možností, jak zadat uvozovky, apostrofy a jiné zvláštní znaky, je “escapovat” je, tj. napsat je pomocí zpětného lomítka \ a vybraného znaku (např. \" znamená uvozovku, \n konec řádku apod.).
x1 <- TRUE  # logická hodnota
x1
[1] TRUE
x2 <- 1L  # celé číslo
x2
[1] 1
x3 <- 1  # reálné číslo
x3
[1] 1
x4 <- 'Josef řekl: "Miluji R!"'  # řetězec
x4
[1] "Josef řekl: \"Miluji R!\""

Při zadávání reálných čísel se desetinná místa oddělují tečkou, ne čárkou.

1.3
[1] 1.3

Čárky oddělují parametry ve funkcích – jinde způsobí chybovou hlášku!

1,3
Error in parse(text = input): <text>:1:2: unexpected ','
1: 1,
     ^

Reálná čísla jde zadat i pomocí tzv. “vědecké notace”, kde číslo před e je mantisa, číslo za e dekadický exponent:

1.3e3   # 1.3 krát 10 na třetí, tj. 1 300
[1] 1300
2.7e-5  # 2.7 krát 10 na minus pátou, tj. 0.000027
[1] 2.7e-05

R někdy reálná čísla takto samo vypisuje. Pokud chcete ovlivnit, jak bude reálné číslo vypsané, můžete použít funkci format() (víc parametrů najdete v nápovědě funkce):

format(2.7e-5, scientific = FALSE)
[1] "0.000027"

Mezi proměnnou typu integer a double je několik rozdílů. Hlavní z nich se týká přesnosti: typ integer sice umí zahrnout jen celá čísla, reprezentuje je však naprosto přesně. Naproti tomu typ double umí zahrnout i desetinná čísla (a také velmi velká čísla), reprezentuje je však pouze přibližně, takže v následujícím výpočtu vznikne chyba, i když velmi malá:

sqrt(2) ^ 2 - 2  # odmocnina 2 umocněná na druhou minus 2
[1] 4.440892e-16

3.2 Testování datového typu

R umožňuje otestovat, jaký datový typ má zvolená proměnná, pomocí funkcí is.X(), kde X je daný datový typ. Tyto funkce vrací TRUE, pokud je daná proměnná daného datového typu. Existuje i funkce is.numeric(), která vrací hodnotu TRUE v případě, že proměnná je číselná, ať už celočíselná nebo reálná.

Funkce typeof() vrací datový typ proměnné jako řetězec (např. "logical"). Podobná, ale zdaleka ne stejná, je funkce class(), která vrací třídu objektu z hlediska objektově orientovaného programování. Pro atomické vektory však vrací typ proměnných.

typeof(x1)
[1] "logical"
is.logical(x1)
[1] TRUE
is.numeric(x1)
[1] FALSE
typeof(x2)
[1] "integer"
is.integer(x2)
[1] TRUE
is.numeric(x2)
[1] TRUE
typeof(x3)
[1] "double"
is.integer(x3)
[1] FALSE
is.double(x3)
[1] TRUE
is.numeric(x3)
[1] TRUE
typeof(x4)
[1] "character"
is.character(x4)
[1] TRUE

Podobné, ale poněkud přísněji se chovající testy nabízí balík purrr, např.:

purrr::is_integer(x1)
[1] FALSE

3.3 Chybějící a “divné” hodnoty

V některých případech může proměnná obsahovat příznak, že její hodnota chybí nebo je chybná. R k tomu má tři speciální hodnoty:

  • NA je chybějící hodnota (“not available”). Existuje pro všechny základní datové typy.
  • NaN znamená, že numerická hodnota není číslo, ale je chybná (“not a number”). Tato hodnota existuje jen pro typ double.
  • Inf označuje kladnou nekonečnou hodnotu; podobně -Inf zápornou nekonečnou hodnotu. Obě hodnoty také existují jen pro typ double.

Nekonečná hodnota vznikne např. při dělení nenulového čísla nulou:

1 / 0
[1] Inf

Chybná hodnota vznikne při různých nepovolených matematických operacích, které však nevedou na nekonečno, např. při dělení nuly nulou:

0 / 0
[1] NaN

Chybějící hodnoty NA se obvykle používají při zadávání hodnot v konzoli nebo ve skriptu a při ukládání čísel do souboru, aby se označilo, která hodnota chybí. Mohou však také být výsledkem výpočtu, když danou operaci není možné provést, ale nejedná se při tom o neplatné počítání s čísly, které by vedlo na Inf nebo NaN.

Existují testy, které testují, zda je hodnota proměnné NA, NaN nebo Inf, a které vracejí jako výsledek logickou hodnotu testu TRUE nebo FALSE: is.na(), is.nan(), is.finite() a is.infinite(). Funkce is.infinite() vrací TRUE jak pro Inf, tak i pro -Inf; funkce is.finite() naopak. Pozor: funkce is.na() vrací TRUE jak pro NA, tak i pro NaN.

Stejně jako ostatní hodnoty v R, tak i chybějící hodnoty NA mají svůj typ. V celočíselné proměnné je tak NA ve skutečnosti reprezentované jako NA_integer_, zatímco v reálné proměnné jako NA_real_ apod. Pokud byste vypsali obsah těchto dvou proměnných na obrazovku, uvidíte NA; pokud byste použili k otestování shody jejich obsahu funkci identical() (viz dále), zjistíte, že hodnoty nejsou stejné:

x1 <- c(1L, NA)[2]   # vezme se druhá hodnota celočíselného vektoru
x2 <- c(1, NA)[2]    # vezme se druhá hodnota reálného vektoru
x1
[1] NA
x2
[1] NA
identical(x1, x2)
[1] FALSE

Velmi speciální hodnotou je NULL. NULL je speciální objekt (má vlastní datový typ) a zároveň rezervované slovo, které R vrací v situaci, kdy nějaká hodnota není definovaná nebo nějaký vektor neexistuje. NULL se často chová jako vektor nulové délky. K otestování, zda je hodnota objektu NULL slouží funkce is.null().

3.4 Převody mezi datovými typy

V případě, že R potřebuje nějakým způsobem sladit dva základní datové typy (např. je spojit do jednoho atomického vektoru), provede R jejich automatickou konverzi a převede jednodušší typ na obecnější typ. Převod probíhá od logických proměnných k celočíselným (TRUE se převede na 1 a FALSE na 0), od celočíselných k reálným a od nich k řetězcům. Při automatické konverzi záleží na pořadí:

# funkce c() spojí hodnoty v závorkách do vektoru a převede je na řetězec
c(TRUE, 1L, 1, "1")
[1] "TRUE" "1"    "1"    "1"   
c(c(TRUE, 1L), 1, "1")
[1] "1" "1" "1" "1"
c(c(TRUE, 1L, 1), "1")
[1] "1" "1" "1" "1"

Automatické konverze lze někdy využít k zajímavým trikům. Pokud např. chceme sečíst počet případů, ve kterých platí nějaká podmínka, jde použít na logický vektor numerickou funkci pro součet hodnot prvků vektoru sum() a využít automatickou konverzi:

x <- c(1, 2, 3, 7, 19, 31)  # vytvoří vektor daných čísel
# kolik hodnot x je větší než 10?
sum(x > 10)
[1] 2

Výraz sum(x > 10) se vyhodnotí postupně: nejdříve se vyhodnotí výraz x > 10, jehož výsledkem je logický vektor, kde je každé číslo větší než 10 nahrazeno TRUE a každé číslo menší rovno 10 nahrazeno FALSE. Ve druhém kroku R automaticky nahradí každé TRUE jedničkou a každé FALSE nulou. Ve třetím kroku sečte vektor jedniček a nul.

V některých situacích je třeba provést konverzi ručně. K tomu slouží funkce as.X(), kde X je jméno datového typu.

as.character(TRUE)
[1] "TRUE"
as.integer(TRUE)
[1] 1

Při převodu čísel na logické hodnoty se nula převede na FALSE a ostatní čísla na TRUE:

as.logical(c(-1, 0, 0.1, 1, 2, 5))
[1]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE

Překvapivě je možné převést i řetězce na čísla nebo na logické hodnoty, pokud dané řetězce obsahují číselné nebo logické hodnoty. Tyto operace však nemusejí být bezpečné.

as.integer("11")
[1] 11
as.double("11.111")
[1] 11.111
as.logical("TRUE")
[1] TRUE

Někdy R neví, jak nějaký objekt převést. Pak je výsledkem hodnota NA a R vydá varování:

x <- "ahoj"
as.numeric(x)
Warning: NAs introduced by coercion
[1] NA

Poznámka: V R je zvykem, že objekty mají testovací funkci is.X a konverzní funkci as.X. Neplatí to sice vždy, ale valná většina objektů tyto funkce má.

3.5 Základní aritmetické operace

Základní aritmetické operace jsou sčítání (+), odčítání (-), násobení (*), dělení (/) a umocňování (^). K celočíselnému dělení slouží symbol %/%, zbytek po dělení vrací %%:

1 + 2
[1] 3
3 * 4
[1] 12
12 / 4
[1] 3
2 ^ 3
[1] 8
9 %/% 2
[1] 4
9 %% 2
[1] 1

Operátory mají normální prioritu, na jakou jsme zvyklí z matematiky, tj. součin má přednost před sčítáním apod.:

1 + 2 * 3  # 7, nikoli 9
[1] 7

Pokud potřebujeme změnit pořadí vyhodnocování výrazů, slouží k tomu stejně jako v matematice obyčejné kulaté závorky:

(1 + 2) * 3  # 9, nikoli 7
[1] 9

Aritmetické operace mohou změnit typ proměnné. Např. výsledek dělení dvou celých čísel je vždy proměnná typu double, a to i v případě, že je výsledek celočíselný:

x <- 2L / 1L
x
[1] 2
typeof(x)
[1] "double"

3.6 Srovnání čísel

Ke srovnání aritmetických hodnot slouží následující operátory: porovnání shody celých čísel (==), různosti celých čísel (!=), větší (<), větší rovno (<=), menší (>) a menší rovno (>=). Výsledkem srovnání je logická hodnota TRUE nebo FALSE:

1L == 3L
[1] FALSE
2L == 2L
[1] TRUE
1L != 3L
[1] TRUE
1 < 3
[1] TRUE
1 > 3
[1] FALSE

Srovnávat shodu nebo různost dvou reálných čísel není pomocí operátorů == a != rozumné. R sice srovnání provede, ale to nemusí mít žádný smysl, jak ukazuje následující příklad:

x1 <- 0.5 - 0.3
x2 <- 0.3 - 0.1
x1 == x2                           # na většině počítačů FALSE
[1] FALSE

Důvod je ten, že necelá čísla, která v desítkové soustavě vypadají nezáludně, není vždy možné vyjádřit dobře ve dvojkové soustavě a výsledek se proto zaokrouhluje. Proto přestože je výsledek předchozích operací v desítkové soustavě stejný (1/5), ve dvojkové soustavě dopadne jinak.

Ke srovnání dvou reálných čísel slouží následující idiom:

identical(all.equal(x1, x2), TRUE) # TRUE všude
[1] TRUE

Funkce all.equal() vrací logickou hodnotu TRUE, pokud jsou všechny prvky dvou vektorů stejné; jinak vrací komentář k velikosti rozdílů. Ovšem “jsou stejné” je v této funkci chápáno volně: dvě reálná čísla jsou stejná, pokud se neliší více než o několik násobků strojové přesnosti počítače. Funkce identical() vrací logickou hodnotu TRUE, pokud jsou dva objekty identické; jinak vrací FALSE. Dohromady vrátí fráze hodnotu TRUE jen v případě, kdy jsou obě téměř stejná (až na chybu, která zřejmě vznikla kvůli tomu, jak jsou reálná čísla v počítači uložená).

Balík dplyr nabízí ke srovnání hodnot typu double příjemnou funkci near()

dplyr::near(x1, x2)  # TRUE všude
[1] TRUE

3.7 Základní logické operace

Základní logické operace zahrnují logický součin (“a zároveň”, &), logický součet (“nebo”, |) a negaci (“opak”, !). Kromě toho samozřejmě fungují i závorky. Význam jednotlivých operací ukazuje tabulka 3.1. Všimněte si, že !(V1 & V2) \(=\) !V1 | !V2 a !(V1 | V2) \(=\) !V1 & !V2.

Tabulka 3.1: Význam základních logických operací.
V1 V2 V1 & V2 V1 | V2 !V1 !(V1 & V2) !(V1 | V2)
TRUE TRUE TRUE TRUE FALSE FALSE FALSE
TRUE FALSE FALSE TRUE FALSE TRUE FALSE
FALSE TRUE FALSE TRUE TRUE TRUE FALSE
FALSE FALSE FALSE FALSE TRUE TRUE TRUE

Logický součin a součet existují v R ve dvou formách: jednoduché a “zkratující”. Ta druhá operátory zdvojuje, takže místo & se použije && a místo | se použije ||. Jednoduchá forma se používá při vyhodnocování operátorů na logických vektorech, kde pracuje “po prvcích”, tj. logická operace se použije nejdříve na pár prvních hodnot v obou vektorech, pak na druhý pár atd. Výsledkem je opět vektor:

c(TRUE, TRUE, FALSE, FALSE) & c(TRUE, FALSE, TRUE, FALSE)
[1]  TRUE FALSE FALSE FALSE
c(TRUE, TRUE, FALSE, FALSE) | c(TRUE, FALSE, TRUE, FALSE)
[1]  TRUE  TRUE  TRUE FALSE

Zkratující forma se používá v podmínkách, viz oddíl 6.1. V tomto případě se pracuje pouze s logickými skaláry (vektory délky 1). Vyhodnocování výrazu se navíc zastaví ve chvíli, kdy je výsledek jednoznačně známý, tj. např. ve výrazu

FALSE && !(TRUE || FALSE)
[1] FALSE

vyhodnocování skončí hned prvním FALSE, protože po jeho vyhodnocení výsledek jasný. Pokud byste použili zkratující formu na vektory, dostanete od R verze 4.3 chybové hlášení (ve starších verzích by výpočet proběhl a výsledek by závisel jen na prvních prvcích vektorů):

c(TRUE, FALSE) && c(TRUE, TRUE)
Error in c(TRUE, FALSE) && c(TRUE, TRUE): 'length = 2' in coercion to 'logical(1)'

Vektorová funkce all() vrátí TRUE, pokud jsou všechny prvky vektoru TRUE; jinak vrátí FALSE. Vektorová funkce any() vrátí TRUE, pokud je aspoň jedna hodnota TRUE; jinak vrátí FALSE. (Jedná se tedy o logický součin a součet přes všechny prvky vektoru.) Funkce all.equal() a identical() byly představeny výše.

all(c(TRUE, TRUE, TRUE))
[1] TRUE
all(c(TRUE, TRUE, FALSE))
[1] FALSE
any(c(TRUE, TRUE, FALSE))
[1] TRUE
any(c(FALSE, FALSE, FALSE))
[1] FALSE

To má mimo jiné důležitý důsledek: Pokud např. chcete otestovat, že proměnná p obsahuje číselné hodnoty a všechny její prvky jsou kladné, nemůžete napsat

p <- 1:-1
is.numeric(p) && p > 0
Error in is.numeric(p) && p > 0: 'length = 3' in coercion to 'logical(1)'

protože is.numeric(p) se vyhodnotí jako TRUE, zatímco p > 0 jako logický vektor (TRUE, FALSE, FALSE). Zkratující && pracuje od R verze 4.3 jen se známými logickými vektory délky 1, proto výpočet skončí chybou. (Ve starších verzích by R vzalo z tohoto vektoru první prvek, takže by vrátilo TRUE, což není to, co bychom očekávali). V tomto případě je tedy potřeba použít

is.numeric(p) && all(p > 0)
[1] FALSE

3.8 Priorita základních operátorů

Při vyhodnocování výrazů se R řídí prioritou a asociativitou operátorů. Operace s vyšší prioritou se provedou dříve než operace s nižší prioritou. (To znáte z matematiky: násobení a dělení mají přednost před sčítáním a odčítáním.)

Priorita operátorů v R uspořádaná od nejvyšší po nejnižší je následující:

  1. závorky: ()
  2. umocňování: ^
  3. unární operátory: +, -, ! (výrazy typu \(-1\) a !TRUE)
  4. multiplikativní operátory: *, /, %/%, %%
  5. aditivní operátory: +, -
  6. relační operátory: <, >, <=, >=
  7. operátory rovnosti: ==, !=
  8. logický součin (a zároveň): &
  9. logický součet (nebo): |
  10. přiřazovací operátory: <- (a další, o kterých nebudeme mluvit)

To znamená, že výraz

cislo <- 1 + 2 * 3

vyhodnotí takto: Nejprve se vyhodnotí 2 * 3, protože násobení má vyšší prioritu než sčítání. Poté se k výsledku přičte 1, protože sčítání má vyšší prioritu než přiřazení. Nakonec se výsledek přiřadí do proměnné cislo.

Pokud výraz obsahuje operátory se stejnou prioritou, asociativita určuje pořadí jejich vyhodnocení. Většina operátorů se v R vyhodnocuje zleva doprava. Například ve výrazu 1 + 2 - 3 se nejprve vyhodnotí 1 + 2 a poté se od výsledku odečte 3.

Naproti tomu přiřazování pomocí <- funguje zprava doleva. Ve výrazu

z <- y <- x <- 0

se nejprve přiřadí hodnota 0 do x, poté se hodnota x přiřadí do y a nakonec se hodnota y přiřadí do z. Všechny tři proměnné tedy obsahují nulu.