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()
:
## # A tibble: 1,000,000 x 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:
## # A tibble: 3 x 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
- nepřevádí řetězce na faktory,
- 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:
## # A tibble: 1,000,000 x 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:
## # A tibble: 6 x 1
## x
## <int>
## 1 1
## 2 2
## 3 3
## 4 4
## 5 5
## 6 6
## [1] 1 2 3 4 5 6
## 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:
ds <- tibble(a = 1:3, b = 11:13)
ds$c <- ds[, "a"] # vybere se tibble s jedním sloupcem a vloží do sloupce b
ds
## # A tibble: 3 x 3
## a b c$a
## <int> <int> <int>
## 1 1 11 1
## 2 2 12 2
## 3 3 13 3
## # A tibble: 3 x 1
## a
## <int>
## 1 1
## 2 2
## 3 3
## [1] "tbl_df" "tbl" "data.frame"
Správný postup je opět použít operátor, který z dat vybere jeden sloupec:
## # A tibble: 3 x 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
## [1] "integer"
## [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 tibble: 3 x 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()
:
## 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 x 1 1 1 1
## 2 2 12 a 2 2 2
## 3 3 13 <int> 3 3 3