5.5 Tabulky třídy tibble
Kromě tabulek třídy data.frame existuje v R ještě několik dalších typů tabulek. Nejpohodlnější z nich je třída tibble, která je součástí tidyverse, skupiny balíků určených pro datovou analýzu, kterými se budeme zabývat v pozdějších částech tohoto textu. Tato třída tabulek má některé velmi příjemné vlastnosti, pro které je programování s tabulkami třídy tibble pohodlnější než programování s tabulkami třídy data.frame.
Tabulku třídy tibble vytvoříte pomocí funkce tibble()
:
library(tibble)
<- tibble(x = 1:1e6, y = 2 * x, zed = x / 3 + 1.5 * y - 7)
ds ds
## # A tibble: 1,000,000 × 3
## x y zed
## <int> <dbl> <dbl>
## 1 1 2 -3.67
## 2 2 4 -0.333
## 3 3 6 3
## 4 4 8 6.33
## 5 5 10 9.67
## 6 6 12 13
## 7 7 14 16.3
## 8 8 16 19.7
## 9 9 18 23
## 10 10 20 26.3
## # … with 999,990 more rows
Pokud potřebujete vytvořit tabulku třídy tibble ručně, existuje i příjemná funkce tribble()
, která umožňuje zadávat data po řádcích:
tribble(
~name, ~weight, ~height,
"Adam", 68, 193,
"Bětka", 55, 163,
"Cyril", 103, 159
)
## # A tibble: 3 × 3
## name weight height
## <chr> <dbl> <dbl>
## 1 Adam 68 193
## 2 Bětka 55 163
## 3 Cyril 103 159
Ke konverzi jiných tříd na tibble slouží funkce as_tibble()
.
Vytvoření tibble se od vytvoření data.frame v několika ohledech liší: tibble
- nemění “nepovolená” jména sloupců na povolená nahrazením divných znaků tečkami,
- vyhodnocuje své argumenty postupně, takže můžete později zadaný argument použít při tvorbě dříve zadaného argumentu (jako v příkladu výše),
- podporuje jen omezenou recyklaci: všechny zadané vektory musejí mít buď stejnou délku, nebo délku 1,
- nepoužívá jména řádků (která jsou ostatně nebezpečná k uchovávání dat) a
- převod na tibble pomocí
as_tibble()
je rychlejší než převod na data.frame pomocías.data.frame()
.
Liší se také to, jak tibble vypisuje svou hodnotu do konzole. Oproti data.frame zobrazí tibble navíc rozměr tabulky a typ jednotlivých proměnných. Naopak vypíše jen prvních deset řádků a jen takový počet sloupců, které se vejdou na obrazovku. Počet vypsaných řádků je možné ovlivnit ve funkci print()
pomocí parametru n
; počet sloupců pomocí parametru width
, kde width
je maximální počet znaků, které může tibble při tisku použít:
print(ds, n = 5)
## # A tibble: 1,000,000 × 3
## x y zed
## <int> <dbl> <dbl>
## 1 1 2 -3.67
## 2 2 4 -0.333
## 3 3 6 3
## 4 4 8 6.33
## 5 5 10 9.67
## # … with 999,995 more rows
Hlavní rozdíl mezi tibble a data.frame se však týká subsetování: tibble má konzistentnější chování a (na rozdíl od data.frame) vrací vždy stejnou datovou strukturu, což je výhodné zejména při programování. tibble nikdy nezahazuje zbytečné rozměry a ani je nepřidává. To znamená, že []
vždy vrací tibble, zatímco [[]]
a $
vždy vrací vektor. Navíc tibble nikdy nepodporuje partial matching:
<- ds[1:6, ] # omezíme ds na prvních 6 řádků
ds 1] ds[,
## # A tibble: 6 × 1
## x
## <int>
## 1 1
## 2 2
## 3 3
## 4 4
## 5 5
## 6 6
1]] ds[[
## [1] 1 2 3 4 5 6
$z ds
## Warning: Unknown or uninitialised column: `z`.
## NULL
Tato příjemná konzistence má však i svá nebezpečí. Technicky je tibble (stejně jako data.frame) seznamem vektorů. Přestože jsme zatím vždy uvažovali atomické vektory, ve skutečnosti mohou být sloupci tibble i seznamy. To znamená, že následují kód ošklivě selže, protože do proměnné vloží celou tabulku:
<- tibble(a = 1:3, b = 11:13)
ds $c <- ds[, "a"] # vybere se tibble s jedním sloupcem a vloží do sloupce b
ds ds
## # A tibble: 3 × 3
## a b c$a
## <int> <int> <int>
## 1 1 11 1
## 2 2 12 2
## 3 3 13 3
$c ds
## # A tibble: 3 × 1
## a
## <int>
## 1 1
## 2 2
## 3 3
class(ds$c)
## [1] "tbl_df" "tbl" "data.frame"
Správný postup je opět použít operátor, který z dat vybere jeden sloupec:
$d <- ds$a
ds$e <- ds[["a"]]
ds ds
## # A tibble: 3 × 5
## a b c$a d e
## <int> <int> <int> <int> <int>
## 1 1 11 1 1 1
## 2 2 12 2 2 2
## 3 3 13 3 3 3
class(ds$d)
## [1] "integer"
class(ds$e)
## [1] "integer"
Možnost využívající dvojité hranaté závorky se hodí zejména v případě, kdy máte jméno sloupce uložené v nějaké proměnné, takže je nemůžete zapsat přímo:
<- "a"
name $f <- ds[[name]]
ds ds
## # A tibble: 3 × 6
## a b c$a d e f
## <int> <int> <int> <int> <int> <int>
## 1 1 11 1 1 1 1
## 2 2 12 2 2 2 2
## 3 3 13 3 3 3 3
Někdy se nehodí pracovat s tibble (např. proto, že některé funkce očekávají jiný výsledek subsetování). V takovém případě můžete tibble převést na data.frame pomocí konverzní funkce as.data.frame()
:
as.data.frame(ds)
## Warning in format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else x, :
## corrupt data frame: columns will be truncated or padded with NAs
## a b c d e f
## 1 1 11 # A tibble: 3 × 1 1 1 1
## 2 2 12 a 2 2 2
## 3 3 13 <int> 3 3 3