15.4 Implicitní a explicitní chybějící hodnoty
Tabulky často nejsou úplné – některá pozorování chybějí. Chybějící pozorování je účelné rozdělit na implicitní a explicitní.
Rozdíl mezi nimi je demonstrován na následujících tabulkách vytvořených z table1
.
První tabulka table1_expl
obsahuje explicitní chybějící hodnoty. Pozorování (Brazílie v roce 1999) je v tabulce přítomno, ale místo naměřených hodnot vidíme NA
:
<- table1
table1_expl $country == "Brazil" & table1_expl$year == 1999, c("cases","population")] <- NA
table1_expl[table1_expl$country == "Afghanistan" & table1_expl$year == 1999, "cases"] <- NA
table1_expl[table1_expl
print(table1_expl)
## # A tibble: 6 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 NA 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 NA NA
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Tabulka table1_impl
obsahuje implicitní chybějící hodnoty. Pozorování s nenaměřenými chybami v tabulce vůbec není přítomno:
<- table1
table1_impl <- table1_impl[!(table1_impl$country == "Brazil" & table1_impl$year == 1999),]
table1_impl
print(table1_impl)
## # A tibble: 5 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 2000 80488 174504898
## 4 China 1999 212258 1272915272
## 5 China 2000 213766 1280428583
Implicitní chybějící hodnoty jsou při analýze dat velmi zákeřné – nejsou viditelné “pouhým okem” a ani testem na přítomnost NA
:
!complete.cases(table1_impl),] table1_impl[
## # A tibble: 0 × 4
## # … with 4 variables: country <chr>, year <int>, cases <int>, population <int>
15.4.0.1 Odstranění implicitních chybějících hodnot s complete()
Při analýze dat je proto vhodné konvertovat implicitní chybějící hodnoty na explicitní. Pro tento účel je možné použít funkci complete()
:
complete(table1_impl, country, year)
## # A tibble: 6 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 NA NA
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Syntaxe funkce complete()
je velmi přímočará:
complete(data, ..., fill = list())
data
…vstupní tabulka (data frame)...
…sloupce, ze které definují (jednoznačně identifikují) pozorování (v příkladu výšecountry
ayear
)
Ve výchozím nastavení jsou implicitní chybějící hodnoty nahrazeny NA
. Toto chování lze změnit parametrem fill
. Můžeme například vědět, že pokud není žádný případ zaznamenán, tak statistický úřad pozorování nezapisuje – i když by měl správně zapsat hodnotu 0. (Takto skutečně v některých případech postupuje ČSÚ.) Znalost dat nás tedy vede k tomu, že chybějící pozorování ve sloupci cases
jsou ve skutečnosti nulová pozorování. Správně doplněné chybějící hodnoty je tedy možné získat nastavením parametru fill
:
complete(table1_impl, country, year, fill = list(cases = 0))
## # A tibble: 6 × 4
## country year cases population
## <chr> <int> <dbl> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 0 NA
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Do parametru fill
se vkládá list
s pojmenovanými položkami. Jména položek musí odpovídat jménům sloupců v tabulce a musí obsahovat právě jednu hodnotu. Ta je použita pro nahrazení chybějících hodnot.
V příkladu výše zůstalo chybějící pozorování v population
nahrazeno NA
. Pokud není pravidlo pro náhradu explicitně stanoveno ve fill
, zůstává v platnosti výchozí nastavení.
15.4.0.2 Odstranění explicitních chybějících hodnot s drop_na()
V některých případech je naopak vhodné odstranit explicitní chybějící hodnoty a pracovat s tabulkou, ve které jsou implicitní chybějící hodnoty. Pro to je možné využít funkci drop_na()
:
drop_na(table1_expl)
## # A tibble: 4 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 2000 2666 20595360
## 2 Brazil 2000 80488 174504898
## 3 China 1999 212258 1272915272
## 4 China 2000 213766 1280428583
Ve výchozím nastavení drop_na()
zahazuje všechny řádky, na nichž se vyskytla chybějící hodnota – a to v libovolném sloupci. Toto chování lze změnit pomocí jediného dodatečného parametru funkce ...
, který umožňuje specifikovat, které sloupce mají být brány v potaz. Sloupce mohou být identifikovány všemi způsoby srozumitelnými pro dplyr::select()
.
V následujícím příkladě je vypuštěn pouze řádek, ve kterém je chybějící hodnota ve sloupci population
:
drop_na(table1_expl, population)
## # A tibble: 5 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 NA 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 2000 80488 174504898
## 4 China 1999 212258 1272915272
## 5 China 2000 213766 1280428583
15.4.0.3 Nahrazení explicitních chybějících hodnot s fill()
, replace_na()
První funkcí pro nahrazování explicitních chybějících pozorování je replace_na()
. Její syntaxe a fungování je analogické k parametru fill
funkce complete()
. (complete()
je nakonec pouze wrapper okolo replace_na()
a několika dalších funkcí.)
Následující použití replace_na()
nahradí chybějící pozorování ve sloupci cases
nulami a v population
nekonečnem (Inf
):
replace_na(table1_expl, replace = list(cases = 0, population = Inf))
## # A tibble: 6 × 4
## country year cases population
## <chr> <int> <dbl> <dbl>
## 1 Afghanistan 1999 0 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 0 Inf
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
replace_na()
je užitečná ve velmi omezeném množství případů (viz complete()
). Častěji je pravděpoodbně v praxi využívána funkce fill()
. fill()
nahrazuje chybějící hodnotu hodnotou z předcházejícího (výchozí možnost) nebo následujícího řádku. Pozor, fill()
pracuje pouze tehdy, pokud jsou chybějící hodnoty explicitní!
Funkci fill()
je nutné v parametru ...
specifikovat sloupce, u kterých se má nahrazení chybějících hodnot provést. (fill()
opět rozumí všem možnostem dostupným v dplyr::select()
.) Následující ukázka demonstruje úskalí používání funkce fill()
:
fill(table1_expl, cases)
## # A tibble: 6 × 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 NA 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 2666 NA
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
- Chybějící hodnota v prvním řádku nebyla nahrazena – neexistuje totiž žádný předcházející řádek.
- Údaj pro Brazilii byl nahrazen údajem pro Afganistán.
První problém samozřejmě nemá řešení. Výzkumník může zvážit nahrazení hodnotou z následujícího řádku (pomocí parametru .direction = "up"
). Pro druhý problém je řešení následující:
- Rozdělit tabulku na mnoho dílčích tabulek podél proměnné
country
. - Provést nahrazení v každé z nich.
- Tabulky složit zpátky.
Takový úkol je jistě proveditelný, ale velmi složitý. Naštěstí právě takovou funkcionalitu poskytuje group_by()
z balíku dplyr
. group_by()
umožňuje každou definovanou skupinu zpracovat odděleně:
## # A tibble: 6 × 4
## # Groups: country [3]
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 NA 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 NA NA
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
V tomto případě je výsledek v pořádku – Brazílie “nedědí” hodnoty Afganistánu.