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: <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