Rady, které člověk může dostat, se dělí v zásadě do tří kategorií: rady dobré, rady nad kterými stojí za to se zamyslet a rady dobré. Do té poslední kategorie určitě spadá i tenhle tweet.
When you’ve written the same code 3 times, write a function
— David Robinson (@drob) November 9, 2017
When you’ve given the same in-person advice 3 times, write a blog post
Vzhledem k tomu, že jsem přirozeně tvor poměrně líný, mi tahle rada celkem uvízla v hlavě, protože dokáže ušetřit docela dost času.
V poslední době jsem se několikrát potkal s nutností pracovat s různými daty z RÚIANu a ČSÚ. Naštěstí už netřeba složitě hledat, kudy se k příslušným datovým sadám proklikat, neb je v docela slušné podobě odkazuje Národní katalog otevřených dat. Čímž sice odpadá nutnost zdlouhavého hledání, ale pořád je tu problém s nezbytnou předpřípravou dat.
Vzhledem k tomu, že data většinou potřebuju dostat do Rka, abych je mohl zpracovat, rozhodl jsem se, napsat malý balík CzechData, který data automaticky stáhne, z příslušného zdroje, provede nezbytné přípravné kroky (pokud nějaké jsou) a vrátí rozumný formát dat. V případě Rka se tím rozumí data.frame, pakliže se jedná o data prostorová, tak data.frame se sloupcem geometrie (s použitím balíku sf).
Balík s sebou nese něco málo předpřipravených dat. Konkrétně jsou to seznamy obcí, katastrálních území, pou, orp, okresů, krajů a převodním mezi označeními používanými v RÚIANu a ČSÚ. Důvodem je hlavně to, že pro získání např. dat RÚIANu je potřeba znát kód (id) zájmové obce, což není informace, kterou má člověk běžně po ruce. Jedná se čistě o tabelární data, v podstatě číselníky, geometrie se z důvodu velikosti neukládá. Snaha je držet balík tak malý, jak je možné. Aktuálně mají tyto číselníky cca 225 kB, což je relativně rozumné.
Pojďmě se tedy podívat na nějaké ukázky, co se dá s balíkem dělat. Předpokládám alespoň základní orientaci v kódu R. Začneme od potřebných balíků, není jich zrovna málo, ale z většiny budeme potřebovat jen jednu funkci.
library(tidyverse)
library(sf)
library(CzechData)
library(leaflet)
library(RColorBrewer)
library(htmlwidgets)
library(htmltools)
library(DT)
library(rmapshaper)
Nejdřív si načteme do paměti seznam obcí a okresů, aby jsme s nimi mohli pracovat.
data(obce)
data(okresy)
Z okresů si jednoduše vytáhneme kódy, které patří okresům Brna.
id_okresy_Brno <- okresy %>%
filter(str_detect(nazev, "Brno")) %>%
pull(lau1_kod)
A tyto identifikátory použijeme k výběru obcí v okresech Brno a Brno-venkov.
obce_Brno <- obce %>%
filter(lau1_kod %in% id_okresy_Brno)
Zde je výsledná tabulka obcí v okrese Brno venkov.
Toliko k malé ukázce s předpřipravenými daty balíku.
Teď si pojďme ukázat, jak to vypadá v případě, že chceme nějaká získat nějaká prostorová data. Zkusíme si vyrobit jednoduchou mapu volebních okrsků v Brně. Ze seznamu obcí si zjistíme identifikátor Brna následně stáhneme vrstvu volebních okrsků. Pokud by vás zajímalo, jaké další vrstvy se dají z RÚIANu vytáhnout, doporučuji podívat se do helpu funkce load_RUIAN_settlement()
, protože je celkem 11 možných vrstev.
id_obec <- obce %>%
filter(nazev == "Brno") %>%
pull(kod)
volebni_okrsky <- load_RUIAN_settlement(id_obec, layer = "volebni okrsky")
Obdobně fungují i funkce load_cadastral_territory()
a load_RUIAN_state()
, které načítají vrstvy za katastrální území a stát. Jen upozorním, že funkce load_RUIAN_state()
stahuje poměrně velký balík dat, takže může být časově náročnější.
Ze získaných volebních okrsků si ponecháme pouze informaci o čísle okrsku a transformujeme data do souřadnicového systému WGS-84 (crs kód 4326), aby lépe spolupracovala s online mapami. Standardně jsou všechna data v souřadnicovém systému S-JTSK Křovák.
volebni_okrsky <- volebni_okrsky %>%
select(cislo) %>%
st_transform(4326)
Takováto data by se sice dala už přímo vizualizovat pomocí Javaskriptové knihovny leaflet, ale problémem je jejich velikost. Aktuálně má geometrie cca 4.5 MB, což je poměrně hodně, aby se taková data vkládala přímo do webu. Takže je vhodné vrstvu zjednodušit (generalizovat). Nelze ale použít funkci st_simplify()
z balíku sf
, která se sice přímo nabízí, ale bohužel nebere v potaz topologii. Po generalizaci by se tudíž nemusely shodovat sdílené hranice polygonů. Naštěstí existuje balík rmapshaper
s funkcí ms_simplify()
, která provádí generalizaci a respektuje přitom topologii, takže zaručí sdílení hranic polygonů i po zjednodušení. Nastavením dopňujícího parametru ponecháme 10% bodů.
volebni_okrsky <- ms_simplify(volebni_okrsky, keep = 0.1)
Zjednodušená vrstva, o velikosti už jen cca 350 kB lze už bez problémů použít pro vytvoření jednoduché vizualizace nad OpenStreetMap. Jen ještě vhodně naformátujeme jednoduchou popisku. Výslednou mapu pak máme hned pod zdrojovým kódem.
labels <- sprintf("<strong>%s</strong>", volebni_okrsky$cislo) %>%
lapply(htmltools::HTML)
leaflet(data = volebni_okrsky, width = "100%") %>%
addTiles() %>%
addPolygons(fillColor = brewer.pal(8, "Set2"), fillOpacity = 0.4,
stroke = TRUE, weight = 0.5, color = "black",
highlight = highlightOptions(weight = 3,
bringToFront = TRUE),
label = labels)
Dalším krokem může být propojení těchto dat s daty z ČSÚ. Jako příklad vytvoříme vizualizaci počtu obytel ze SLDB za okresy. Začneme získáním vrstvy okresů z RÚIANu, pokud pracujeme stále se stejnou Session R, jako v předchozích příkladech, není nutné znovu stahovat objemnou vrstvu, protože je uložená v dočasném adresáři, se kterým R pracuje. Opět vrstvu zgeneralizujeme, aby se zmenšila velikost, a přehodíme do WGS-84, aby se nemusela provádět změna souřadnic přímo při vizualizaci.
okresy <- load_RUIAN_state(layer = "okresy")
okresy <- ms_simplify(okresy, keep = 0.1)
okresy <- okresy %>%
st_transform(4326)
Nyní potřebujeme získat data o obytelstvu, k tomu slouží funkce load_SLDB_2011()
. Získaná tabulka obsahuje velké množství dat za různé územní celky. Omezíme se pouze na okresy a informaci o počtu obyvatel. Bohužel, ČSÚ používá jiné identifikátory než RÚIAN, takže nelze přímo propojit vrstvu okresů s daty SLDB. Balík CzechData obsahuje tabulku ciselnik_CSU
, která obsahuje převodník mezi indentifikátory. Nejříve tedy propojíme data SLDB s tímto převodníkem a potom můžeme propojit vrstvu okresů s daty SLDB.
sldb <- load_SLDB_2011("obyvatelstvo")
sldb_okresy <- sldb %>%
filter(typ_uzemi == "okres") %>%
select(kod_polozky_uzemniho_ciselniku, obyvatelstvo_celkem)
data(ciselnik_CSU)
sldb_okresy <- sldb_okresy %>%
mutate(kod_polozky_uzemniho_ciselniku =
as.character(kod_polozky_uzemniho_ciselniku)) %>%
left_join(ciselnik_CSU, by = c("kod_polozky_uzemniho_ciselniku" = "kod_csu"))
okresy <- okresy %>%
left_join(sldb_okresy, by = c("kod" = "kod_ruian"))
Stejně jako u předchozí mapy si vytvoříme popisku, která se bude zobrazovat při najetí nad jednotlivé okresy, a barevnou paletu. Pak už jen složíme výslednou mapu.
labels <- sprintf("<strong>%s</strong> - %s obyvatel", okresy$nazev,
format(okresy$obyvatelstvo_celkem, big.mark = " ")) %>%
lapply(htmltools::HTML)
pal <- colorQuantile(palette = "YlOrRd",
domain = okresy$obyvatelstvo_celkem)
leaflet(data = okresy, width = "100%") %>%
addTiles() %>%
addPolygons(fillColor = ~pal(obyvatelstvo_celkem),
fillOpacity = 0.4, stroke = TRUE, weight = 0.5, color = "black",
highlight = highlightOptions(weight = 3,
bringToFront = TRUE),
label = labels)