4 Jak dostat data do R

Do Excelu nebo Google Sheets asi nejčastěji data přímo napíšete nebo odněkud zkopírujete a vložíte. Můžete je také importovat odjinud, třeba z CSV souborů, různých databází nebo API. To vše plus několik dalších způsobů můžete použít i v R.

4.1 Co myslím daty

Spreadsheet je datově velmi jednoduchý. Má jen listy, ty se skládají z buněk a každá buňka může (i nemusí) obsahovat hodnotu. Hodnoty mohou být jen pár typů: číslo, text, logická hodnota (TRUE/FALSE).

R to má trochu složitější. Pro dočasné ukládání dat používá pojmenované objekty (někdy se jim říká proměnné prostředí), které mohou být mnoha typů, jak primitivních (číslo, text apod.), tak složitějších (kterým se většinou říká třída neboli class).

4.1.1 Data frame

Jednomu listu spreadsheetu se nejvíc podobá eRková třída data frame. Je to vlastně klasická datová tabulka s řádky a sloupci. Různé sloupce mohou obsahovat různé typy dat – některé čísla, jiné text – ale v jednom sloupci mohou být data jen jednoho typu. Ukázkovou tabulkou je třeba ceník:

produkt jednotka cena skladem
Malý šroubek 100 g 10.0 TRUE
Velký šroub ks 5.0 TRUE
Malá matička 100 g 8.5 FALSE
Velká matka ks 6.0 TRUE

První dva sloupce obsahují text, třetí sloupec čísla a poslední sloupec logické hodnoty (někdy označované jako boolean): TRUE je pravda, FALSE je nepravda.

Teď už tedy víte, co je data frame, a v dalším textu vám ukážu, jak ho vytvořit a dostat do něj data.

4.2 Ruční vstup dat

V Excelu data ručně vkládáte rovnou do buněk listu. To sice jde v R také, ale většinou se to nedělá. Místo toho se napíše příkaz (nebo krátký skript čili posloupnost příkazů), který vytvoří data frame, naplní ho daty a výsledek uloží do objektu, se kterým můžete dál pracovat.

4.2.1 Funkce data.frame

Konkrétně ceník výše jsem vytvořil tímto příkazem:

sample_df <- data.frame(
  produkt = c("Malý šroubek", "Velký šroub", "Malá matička", "Velká matka"),
  jednotka = c("100 g", "ks", "100 g", "ks"),
  cena = c(10, 5, 8.5, 6),
  skladem = c(TRUE, TRUE, FALSE, TRUE)
)

Vysvětlím podrobněji:

  1. Do objektu sample_df přiřadím (neboli uložím) výsledek funkce data.frame. To jde zjednodušeně napsat jako sample_df <- data.frame(...), kde tři tečky reprezentují tzv. argumenty (nebo též parametry) funkce data.frame. Znaky <- se v R používají k přiřazení (uložení) hodnoty do objektu a v RStudiu je můžete zadat klávesou zkratkou Alt+- (Alt pomlčka).
  2. Argumenty funkce data.frame jsou jednotlivé sloupce, které má data frame mít. Zde to je produkt, jednotka, cenaskladem. Vzájemně jsou odděleny čárkou, na rozdělení do řádků nezáleží.
  3. Sloupce se definují jako název_sloupce = vektor, přičemž vektor musí určovat hodnoty všech řádků data framu.
  4. V příkladu vektory zadávám jako výsledek funkce c. Ta vezme všechny své argumenty (oddělené čárkou) a vytvoří z nich vektor. Všimněte si, že textové hodnoty se píší do uvozovek, kdežto číselné a logické ne.

Jakmile máte data frame vytvořený a uložený do objektu sample_df, můžete s ním dál pracovat, např. vypsat jeho obsah:

sample_df

4.2.2 Funkce tibble

Já raději používám funkce z ekosystému tidyverse, ve kterém funkci data.frame nahrazuje funkce tibble. Používá se úplně stejně, ale místo objektu třídy data frame vytvoří objekt třídy tibble, který je s data framem plně kompatibilní, ale o něco hezčeji se vypisuje na konzoli.

Příkaz s touto funkcí pak vypadá takto:

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.1.3
sample_df <- tibble(
  produkt = c("Malý šroubek", "Velký šroub", "Malá matička", "Velká matka"),
  jednotka = c("100 g", "ks", "100 g", "ks"),
  cena = c(10, 5, 8.5, 6),
  skladem = c(TRUE, TRUE, FALSE, TRUE)
)

Povšimněte si, že abych mohl funkci tibble použít, musím nejdřív načíst balíček tidyverse funkcí library.

4.2.3 Funkce tribble

Oba výše popsané způsoby zadávání dat do data framu mají jednu nevýhodu: data zapisujete po sloupcích, ačkoli je většinou přirozenější je psát po řádcích. Tuto nevýhodu řeší funkce tribble, která je taktéž součástí ekosystému tidyverse.

Používá se takto:

sample_df <- tribble(
  ~produkt, ~jednotka, ~cena, ~skladem,
  "Malý šroubek", "100 g", 10, TRUE,
  "Velký šroub", "ks", 5, TRUE,
  "Malá matička", "100 g", 8.5, FALSE,
  "Velká matka", "ks", 6, TRUE
)

Názvy sloupců jsou v prvním řádku a každý začíná znakem ~. Pak následují jednotlivé řádky s hodnotami. Vše je navzájem odděleno čárkou.

Pokud chcete mít funkci tribble ve skriptu úhledně upravenou a dobře čitelnou, můžete přidat i mezery, např. takto:

sample_df <- tribble(
  ~produkt,       ~jednotka, ~cena, ~skladem,
  "Malý šroubek", "100 g",   10,    TRUE,
  "Velký šroub",  "ks",       5,    TRUE,
  "Malá matička", "100 g",    8.5,  FALSE,
  "Velká matka",  "ks",       6,    TRUE
)

4.2.4 Co když chci něco opravit?

To je všechno moc hezké, říkáte si, ale v Excelu mohu nejen ručně zadat data, ale i kdykoli cokoli dodatečně opravit. Jak to udělám v R?

Inu, skoro stejně. V Excelu něco píšete, pak máte už hotový výsledek a ten opravíte. V R nepíšete rovnou výsledek, nýbrž postup, jak výsledek vytvořit. Opravíte tedy postup, znovu ho spustíte a získáte opravený výsledek. Vypadá to o trochu složitěji, ale ve skutečnosti je to o dost lepší, protože informace o postupu zůstane zaznamenaná.

  1. Pokud máte postup uložený ve skriptu, opravíte ho a znovu pustíte skript.
  2. Pokud máte postup v souboru rmarkdown (.Rmd), opravíte ho a znovu spustíte jen opravený blok.
  3. Pokud jste postup napsali jen do konzole, vrátité se k němu v historii (v konzoli šipka nahoru, případně panel History v RStudiu), opravíte a znovu provedete.

4.2.5 Funkce edit

Ve skutečnosti můžete i v R opravovat data skoro stejně, jako v Excelu. Slouží k tomu funkce edit, která otevře jednoduchý tabulkový editor, do něj načte data frame uvedený v jejím argumentu, a když v editoru cokoli změníte a pak ho zavřete, vrátí zpátky opravená data.

V následujícím příkladu vyvolám editor pro objekt sample_df a výsledek zapíšu zpět do stejného objektu, takže pak bude obsahovat již opravená data. Tímto způsobem se ale ztratí postup vzniku dat, a proto se v R skoro nepoužívá.

sample_df <- edit(sample_df)

4.3 Chci si jen rychle něco vyzkoušet

V základním R i v některých balíčcích je docela dost vzorových data setů již zabudovaných. Slouží jako příklady pro demonstraci některých postupů a můžete si s nimi zkusit hrát. Často se třeba něco ukazuje na datasetu iris, který obsahuje vlastnosti několika druhů kosatců.

iris

A v tidyverse ze zabudovaný i krásný dataset postav ze Star Wars.

starwars

4.4 Práce s CSV soubory

V reálné praxi se data do R nejčastěji načítají z CSV souborů. Abyste si to mohli hned vyzkoušet i v případě, že zrovna nemáte žádný CSV po ruce, nejdřív vám ukážu, jak do CSV zapisovat.

4.4.1 Funkce write_csv

CSV soubor pro další pokusy vytvořím z data framu sample_df. S funcí write_csv z balíčku readr (součást tidyverse) Je to takhle jednoduché:

write_csv(sample_df, "sample_df.csv")

4.4.2 Funkce read_csv

Obdobně lze data z CSV souboru načíst funkcí read_csv:

sample_df <- read_csv("sample_df.csv")
## Rows: 4 Columns: 4
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (2): produkt, jednotka
## dbl (1): cena
## lgl (1): skladem
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.

Všimněte si, že funkce vypsala specifikaci sloupců a jejich datových typů. Datové typy odhaduje z obsahu souboru a ne vždy je trefí správně, takže někdy může být potřeba je určit ručně, ať už v parametrech funkce read_csv, nebo v dodatečné úpravě získaného data framu.

4.4.3 Interaktivní import dat v Rstudiu

Pokud nevíte přesně, jak importovaný soubor vypadá, je v RStudiu nejjednodušší zvolit příkaz Import Dataset z menu File. Tam si pak můžete na živém náhledu dat vybrat, co přesně chcete importovat, které sloupce jsou kterého typu apod.

Podstatné je, že se vám současně generuje i skript, který si můžete zkopírovat pro opakované použití se stejným souborem.

4.4.4 Načtení CSV z webu

Funkcí read_csv a dalšími funkcemi z balíčku readr (součást tidyverse) můžete načítat i vzdálené soubory z internetu. Místo cesty a názvu lokálního souboru pak zadáte jeho URL.

Ukážu trochu komplexnější příklad, který načte data z veřejného datasetu zvířat k adopci pražské ZOO.

animals <- read_delim(
  "https://opendata.praha.eu/dataset/9e9ec749-db30-4f0d-bb02-5b48cf090888/resource/f4432746-002d-45dd-bb09-d1719acf35fb/download/959c0e6f-5afb-489f-95ef-c9c2982963de-adopcezvirata.csv", 
  delim = ";", 
  col_types = cols(
    id = col_skip(), 
    nazev_en = col_skip(), 
    k_prohlidce = col_logical(), 
    ...7 = col_skip()
  ), 
  trim_ws = TRUE
)
## New names:
## * `` -> ...7
## Warning: One or more parsing issues, see `problems()` for details
animals

Co přesně jsem udělal?

  • Protože dataset odděluje sloupce středníky a ne čárkami, použil jsem místo funkce read_csv obecnější funkci read_delim, která umožňuje oddělovač nastavit parametrem delim.
  • V parametru col_types jsem funkcí cols určil, které sloupce nechci importovat (col_skip) a sloupci k_prohlidce jsem nastavil logický typ (v původních datech je hodnota 0 a 1).
  • Parametrem trim_ws jsem určil, že se mají odstranit nevýznamné mezery na začátku a konci hodnot.

4.5 Data na webové stránce

Nakonec vám ukážu, jak snadno můžete načítat data z webových stránek. Ukážu to na tabulce v HTML, se kterou se pracuje nejsnáz, ale jde to i se stránkami, kde jsou data uspořádaná jinak.

Ideální tabulka je např. na stránce Seznam hlavních měst států světa ve Wikipedii. Načtu ji skriptem, který:

  1. Připojí balíček rvest pro stahování informací z webu.
  2. Do objektu hlavni_mesta přiřadí výsledek funkce html_table. Ta vrátí všechny HTML tabulky, které na stránce jsou.
  3. Jako parametr funkce html_table zavolá funkci read_html, která načte webovou stránku ze zadaného URL.
  4. Indexem [[1]] z vráceného seznamu tabulek vybere tu první.
  5. Zobrazím, co se do objektu hlavni_mesta uložilo.
library(rvest)
## Warning: package 'rvest' was built under R version 4.1.3
## 
## Attaching package: 'rvest'
## The following object is masked from 'package:readr':
## 
##     guess_encoding
hlavni_mesta <- html_table(
  read_html(
    "https://cs.wikipedia.org/wiki/Seznam_hlavn%C3%ADch_m%C4%9Bst_st%C3%A1t%C5%AF_sv%C4%9Bta"
  )
)[[1]]

hlavni_mesta

Asi jste si všimli, že získaná data nejsou perfektní. Ve sloupci stát je název každá země dvakrát. Je to proto, že ve zdrojové tabulce jsou před názvem země vlajky, které název obsahují v atributu alt. Navíc je počet obyvatel typu text, protože si funkce neporadí s českými mezerami mezi řády.

Obojí jde snadno napravit. Ukážu vám jak, ale už to zatím nebudu podrobně vysvětlovat. To si necháme na jindy.

mutate(
  hlavni_mesta,
  Stát = str_sub(Stát, 1, nchar(Stát) / 2),
  Obyvatel = as.double(str_remove_all(Obyvatel, "\\s"))
)

4.6 Data z jiných zdrojů

Pomocí různých balíčků jde načítat data i z jich typů zdrojů. Já třeba nejčastěji pracuji s daty Google Search Console nebo Google Analytics, která načítám přes API (aplikační rozhraní) resp. prostřednictvím specializovaných balíčků, které toto API zpřístupňují. Pracovat jde i s daty ve všech běžných SQL i NoSQL databázích. Tyto metody jsou už ale nad rámec tohoto článku.