Je to velmi široké téma a my se naučíme jenom to, jak tyto hodnoty detekovat a nahradit je jinými, nebo eliminovat datové elementy, kde se vyskytují. Speciálních hodnot je několik druhů podle toho, jak vznikly.
Excel: “#N/A”, “”
+ možná odlehlá hodnota?
+ nedělím někde nulou?
tabulka <- data.frame(pocet_deti = c(3, NA, NA, NA), rok_narozeni = c(1940, 2015, 2001, 2003), dosazene_vzdelani = c("VŠ", NA, "ZŠ", NA))
Testovací funkce is.na() vrátí data.frame o stejných rozměrech s hodnotami TRUE nebo FALSE v každé buňce.
is.na(tabulka)
## pocet_deti rok_narozeni dosazene_vzdelani
## [1,] FALSE FALSE FALSE
## [2,] TRUE FALSE TRUE
## [3,] TRUE FALSE FALSE
## [4,] TRUE FALSE TRUE
Když tuto funkci zkombinujeme s funkcí any(), dostaneme okamžitou odpověď na otázku, zda se v datech vyskytují nějaké hodnoty NA. To se hodí například do podmínek.
any(is.na(tabulka))
## [1] TRUE
Kolik jich je?
sum(is.na(tabulka))
## [1] 5
Už taky víme, jak si udělat rychlý přehled “pro lidské oko” pomocí summary().
summary(tabulka)
## pocet_deti rok_narozeni dosazene_vzdelani
## Min. :3 Min. :1940 VŠ :1
## 1st Qu.:3 1st Qu.:1986 ZŠ :1
## Median :3 Median :2002 NA's:2
## Mean :3 Mean :1990
## 3rd Qu.:3 3rd Qu.:2006
## Max. :3 Max. :2015
## NA's :3
Pokud jde o tabulky, víme, že pozorování bývají v řádcích a proměnné ve sloupcích. Statistiky jednotlivých proměnných se počítají z jednotlivých řádků. Pokud budeme provádět nějakou analýzu, která nesnese hodnotu NA v proměnné, budeme muset odstranit všechny řádky, v kterých některá proměnná nabývá hodnoty NA. Jak je snadno detekujeme? Pomocí funkce complete.cases(). Ta vydá TRUE nebo FALSE pro každý řádek tabulky, jestli je “kompletní”, tj. _bez hodnoty NA .
Podobně můžeme použít funkci table() na každý sloupec:
table(tabulka$pocet_deti)
##
## 3
## 1
table(tabulka$rok_narozeni)
##
## 1940 2001 2003 2015
## 1 1 1 1
table(tabulka$dosazene_vzdelani, useNA = "ifany")
##
## VŠ ZŠ <NA>
## 1 1 2
complete.cases(tabulka)
## [1] TRUE FALSE FALSE FALSE
Jediným kompletním případem byl ten první, protože ostatní měli NA ve vzdělání nebo/a počtu dětí. Tato funkce nepodává informaci o tom, v kterém sloupci to NA je.
Mimochodem, porovnávací a třídící funkce nepovažují dvě NA za shodné hodnoty! S NA prostě nefunguje nic rozumného!
NAOdstranění řádků je snadné pomocí subsetu s funkcí complete.cases() jako logickým testem. Jde to oběma způsoby - přes hranatou závorku i přes funkci subset(), kam se ani nemusí psát == TRUE.
tabulka[complete.cases(tabulka),]
## pocet_deti rok_narozeni dosazene_vzdelani
## 1 3 1940 VŠ
subset(tabulka, complete.cases(tabulka))
## pocet_deti rok_narozeni dosazene_vzdelani
## 1 3 1940 VŠ
Ještě na to taky existuje speciální funkce na.omit()
na.omit(tabulka)
## pocet_deti rok_narozeni dosazene_vzdelani
## 1 3 1940 VŠ
NA na místa prázdných hodnotNA něco jiného a vyrobíme si takovou z naší původní tabulky, aniž bychom její sloupce konvertovali na znakové vektory (protože teď jsou to faktory, samozřejmě).Editování faktorů je dobré proto, že by při konverzi ze znakového vektoru mohlo dojít ke zmatku, zda se hodnota NA načte správně, nebo jako řetězec "NA", což by data znehodnotilo.
Připravíme si tabulku pojmenovanou tabulka2, která bude mít ve sloupci vzdělání místo NA slovo “žádné”. Je to taky příležitost k nahlédnutí do editace faktorů (skoro se to nedá a nikdo to nedělá, když nemusí!!!)
tabulka2 <- tabulka
tabulka2$dosazene_vzdelani <- factor(tabulka2$dosazene_vzdelani, levels = c(levels(tabulka2$dosazene_vzdelani), ""))
str(tabulka2)
## 'data.frame': 4 obs. of 3 variables:
## $ pocet_deti : num 3 NA NA NA
## $ rok_narozeni : num 1940 2015 2001 2003
## $ dosazene_vzdelani: Factor w/ 3 levels "VŠ","ZŠ","": 1 NA 2 NA
Na faktorech je zrádné i to, že s názvy úrovní se nedá manipulovat mimo parametr levels ve funkci factor(). Sice existuje funkce levels(), ale ta je obecnější a u faktorů nedělá, co bychom mysleli. Zatímco u pojmenování sloupců je snad úplně jedno, jestli je pojmenujete už při vytvoření data.framu parametrem col.names, nebo dodatečně funkcí colnames(), u faktoru to jedno není. Tak proto jsme zopakovali funkci factor na něčem, co už faktor bylo – jen abychom tomu změnili počet a názvy parametru levels!
tabulka2$dosazene_vzdelani[which(is.na(tabulka2$dosazene_vzdelani))] <- ""
Nutné dodržet:
+ přidat novou úroveň do parametru ```levels``` ve funkci ```factor```
+ pak v samotném faktoru vybrané elementy nahradit tou slovní hodnotou, *ne její numerickou reprezentací*. To v našem příkladu znamená, že do něčeho, co vypadá jako vektor samých čísel, opravdu přidáte prázdný řetězec ```""```, jakkoli divně to vypadá!
Naše tabulka teď vypadá takhle a je plná faktorů.
tabulka2
## pocet_deti rok_narozeni dosazene_vzdelani
## 1 3 1940 VŠ
## 2 NA 2015
## 3 NA 2001 ZŠ
## 4 NA 2003
str(tabulka2)
## 'data.frame': 4 obs. of 3 variables:
## $ pocet_deti : num 3 NA NA NA
## $ rok_narozeni : num 1940 2015 2001 2003
## $ dosazene_vzdelani: Factor w/ 3 levels "VŠ","ZŠ","": 1 3 2 3
Na doplnění hodnot NA místo prázdného řetězce nebo jiného zástupce hodnot NA, s kterým by si R nevědělo rady vlastně potřebujeme pouze vyhodit název té úrovně ze seznamu úrovní. V našem sloupečku (a možná obecně ve faktorech) se hodnota "" uvádí na posledním, třetím, místě. Připomeňme si, že se hodnoty defaultně řadí abecedně.
levels(tabulka2$dosazene_vzdelani)
## [1] "VŠ" "ZŠ" ""
Nám tedy stačí, když tento řetězec z levels(tabulka2$dosazene_vzdelani) odebereme. Pozor, opět se to musí udělat pomocí parametru funkce factor(), protože R nesnese, že se objekty na levé a pravé straně liší délkou. Vypadla by tato hláška:
> levels(tabulka2$dosazene_vzdelani) <- levels(tabulka2$dosazene_vzdelani)[-3]
Error in `levels<-.factor`(`*tmp*`, value = c("VŠ", "ZŠ")) :
number of levels differs
Takže použijeme celou funkci factor(). Raději si na tuhle operaci založíme další tabulku, tentokrát s číslem 3.
tabulka3 <- tabulka2
tabulka3$dosazene_vzdelani <- factor(tabulka3$dosazene_vzdelani, levels = levels(tabulka3$dosazene_vzdelani)[-3])
tabulka3
## pocet_deti rok_narozeni dosazene_vzdelani
## 1 3 1940 VŠ
## 2 NA 2015 <NA>
## 3 NA 2001 ZŠ
## 4 NA 2003 <NA>
I když se ve faktorovém sloupci hodnoty NA vytisknou ve špičatých závorkách, nic to neznamená. Struktura je správná - v hodnotách sloupce dosazene_vzdelani figurují hodnoty NA, zatímco v seznamu úrovní už není prázdný řetězec. R už tedy bude moci standardně detekovat a zpracovávat chybějící hodnoty.
str(tabulka3$dosazene_vzdelani)
## Factor w/ 2 levels "VŠ","ZŠ": 1 NA 2 NA
is.na(tabulka3$dosazene_vzdelani)
## [1] FALSE TRUE FALSE TRUE
Jen tak na okraj, funkce factor() má parametr exclude, který je defaultně nastaven na NA. Tím jsou nevyplněné hodnoty vyloučeny ze seznamu úrovní. Když se ale parametr nastaví na NULL, tak se vypne a nevyplněné hodnoty se stanou součástí seznamu úrovní a v interní reprezentaci budou nevyplněné hodnoty reprezentovány vlastní číslicí:
tabulka4 <- tabulka3
tabulka4$dosazene_vzdelani <- factor(tabulka4$dosazene_vzdelani, exclude = NULL)
str(tabulka4$dosazene_vzdelani)
## Factor w/ 3 levels "VŠ","ZŠ",NA: 1 3 2 3
Tím se ale Rku řekne, že je nemá detekovat jako NA, což je docela zrada, protože v tom seznamu nejsou v uvozovkách a člověk by myslel, že jsou to prostě pořád poctivé NA!
is.na(tabulka4$dosazene_vzdelani)
## [1] FALSE FALSE FALSE FALSE
Faktory jsou prostě potvory. To, že se špatně editují, je prý nápověda uživatelům, že se editovat nemají, a je to také ochrana před náhodnou typografickou chybou zanesenou do dat během statistické analýzy. Počítá se s tím, že v této fázi práce už se vložená data jenom čtou, ale nic se do nich nezapisuje.