#install.packages("janitor")
library(janitor)
Attaching package: 'janitor'
The following objects are masked from 'package:stats':
chisq.test, fisher.test
Čistenie dát (data cleaning, data cleansing) je proces, pri ktorom odstraňujeme alebo orpavujeme chyby a nezrovnalosti v dátach, aby boli použiteľné na analýzu. Cieľom je, aby údaje boli presné, úplné, konzistentné a mali zmysel pre ďalšie spracovanie.
Typické problémy, ktoré sa pri čistení dát riešia:
duplicitné záznamy
chýbajúce hodnoty
nesprávne alebo nejednotné formáty (napr. dátum vo formáte DD-MM-YYYY a inde MM-DD-YYYY)
preklepy a syntaktické chyby
nepodstatné alebo irelevantné údaje
extrémne hodnoty (outliery), ktoré môžu skresľovať analýzu
Dobre vyčistené dáta sú základom každej analýzy. Ak dáta nie sú kvalitné, výsledky môžu byť zavádzajúce - od nespresných štatistík až po nespoľahlivé predikcie.
Táto knižnica poskytuje jednoduché funkcie, ktoré nám pomôžu rýchlo pripraviť dáta na analýzu - napríklad vyčistiť názvy stĺpcov, nájsť duplicity alebo doplniť chýbajúce hodnoty.
#install.packages("janitor")
library(janitor)
Attaching package: 'janitor'
The following objects are masked from 'package:stats':
chisq.test, fisher.test
Častým problémom sú názvy stĺpcov s nesprávnym syntaxom napr. s medzerami, veľkými písmenami alebo špeciálnymi znakmi. Funkcia clean_names()
všetky názvy prevedie do jednotného, konzistentného tvaru.
Funkcia:
Upraví písmená a oddeľovače na konzistentný formát (predvolený je snake_case
, ale dostupné sú aj iné napr. camelCase
)
Rieši špeciálne znaky a medzery, vrátane transiliterácie znakov
Pridáva čísla k duplicitným názvnom stĺpcov
Konvertuje znaky %
na percent
a #
na number
, aby sa zachoval význam názvu.
Zachováva medzery (alebo ich absenciu) okolo čísel
Príklad
<- as.data.frame(matrix(ncol = 6))
data names(data) <- c("First Name", "Age (Years)", "score %", "repeatVálue", "repeatValue", "")
%>%
data clean_names()
first_name age_years score_percent repeat_value repeat_value_2 x
1 NA NA NA NA NA NA
#> first_name age_years score_percent repeat_value repeat_value_2 x
#> 1 NA NA NA NA NA NA
Základné R by vytvorilo toto:
make.names(names(data))
[1] "First.Name" "Age..Years." "score.." "repeatVálue" "repeatValue"
[6] "X"
#> [1] "First.Name" "Age..Years." "score.." "repeatVálue" "repeatValue" "X"
Pri práci s viacerými súbormi dát, ktoré by mali byť indetické sa často stane, že ich chceme načítať a zlúčiť na analýzu. Niekedy však funkcie ako napr. dplyr::bind_rows()
alebo rbind()
zlyhajúce, pretože stĺpce sa líšia názvom alebo typom.
Funkcia compare_df_cols()
umožňuje rýchlo porovnať viacero data.frameov. Prijíma názvy bez úvodzoviek alebo zoznam data.frameov a vracia zhrnutie ich porovnania. Môžeme zistiť:
Aký je typ jednotlivých stĺpcov
Ktoré stĺpce chýbajú alebo sú prítomné v rôznych objetoch.
Kde sa typy stĺpcov líšia.
Príklad
<- data.frame(a = 1:2, b = c("big", "small"))
df1 <- data.frame(a = 10:12, b = c("medium", "small", "big"), c = 0, stringsAsFactors = TRUE) # here, column b is a factor
df2 <- df1 %>%
df3 ::mutate(b = as.character(b))
dplyr
# Porovnanie všetkých stĺpcov
compare_df_cols(df1, df2, df3)
column_name df1 df2 df3
1 a integer integer integer
2 b character factor character
3 c <NA> numeric <NA>
#> column_name df1 df2 df3
#> 1 a integer integer integer
#> 2 b character factor character
#> 3 c <NA> numeric <NA>
# Len rozdiely medzi stĺpcami
compare_df_cols(df1, df2, df3, return = "mismatch")
column_name df1 df2 df3
1 b character factor character
#> column_name df1 df2 df3
#> 1 b character factor character
# Špecifikácia metódy spájania stĺpcov
compare_df_cols(df1, df2, df3, return = "mismatch", bind_method = "rbind") # default is dplyr::bind_rows
column_name df1 df2 df3
1 b character factor character
2 c <NA> numeric <NA>
#> column_name df1 df2 df3
#> 1 b character factor character
#> 2 c <NA> numeric <NA>
Ak chceme jednoducho zistiť či je možné data.frames úspešne zlúčiť podľa stĺpcov, použijeme compare_df_cols_same()
. Funkcia vráti TRUE
alebo FALSE
.
compare_df_cols_same(df1, df3)
[1] TRUE
#> [1] TRUE
compare_df_cols_same(df2, df3)
column_name ..1 ..2
1 b factor character
[1] FALSE
#> column_name ..1 ..2
#> 1 b factor character
#> [1] FALSE
Pri čistení dát je často potrebné overiť, či sa v dátach nenachádzajú neželané duplikáty. Funkcie v balíku janitor umožňujú rýchlo identifikovať a preskúmať duplicitné záznamy, čo je dôležité najmä v prípadoch, keď by sa mal každý unikátny záznam objaviť v dátach len raz.
Jednou z takýchto funkcií je get_dupes()
. T8 vracia všetky záznamy, ktoré sú duplicitné a pridáva stĺpec s počtom opakovaní, aby bolo jednoduché odhaliť problematické záznamy.
get_dupes(mtcars, wt, cyl) # or mtcars %>% get_dupes(wt, cyl) if you prefer to pipe
wt cyl dupe_count mpg disp hp drat qsec vs am gear carb
1 3.44 6 2 19.2 167.6 123 3.92 18.30 1 0 4 4
2 3.44 6 2 17.8 167.6 123 3.92 18.90 1 0 4 4
3 3.57 8 2 14.3 360.0 245 3.21 15.84 0 0 3 4
4 3.57 8 2 15.0 301.0 335 3.54 14.60 0 1 5 8
#> wt cyl dupe_count mpg disp hp drat qsec vs am gear carb
#> 1 3.44 6 2 19.2 167.6 123 3.92 18.30 1 0 4 4
#> 2 3.44 6 2 17.8 167.6 123 3.92 18.90 1 0 4 4
#> 3 3.57 8 2 14.3 360.0 245 3.21 15.84 0 0 3 4
#> 4 3.57 8 2 15.0 301.0 335 3.54 14.60 0 1 5 8
Pri práci s dátami je užitočné vedieť, či niektoré stĺpce majú jedinečné vzťahy medzi sebou, napr. keď každý záznam v jednom stĺpci zodpovedá presne jednému záznamu v inom stĺpci. Funkcia get_one_to_one()
zobazuje, ktoré stĺpce v dátovom rámci majú medzi sebou one-to-one vzťahy.
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
1:4,] %>%
starwars[get_one_to_one()
[[1]]
[1] "name" "height" "mass" "skin_color" "birth_year"
[6] "films"
[[2]]
[1] "hair_color" "starships"
[[3]]
[1] "sex" "species"
#> [[1]]
#> [1] "name" "height" "mass" "skin_color" "birth_year"
#> [6] "films"
#>
#> [[2]]
#> [1] "hair_color" "starships"
#>
#> [[3]]
#> [1] "sex" "species"
Pri čistení dát z Excelu alebo iných zdrojov sa často stretneme s prázdnymi riadkami a stĺpcami, ktoré po načítaní do R nemajú žiadne hodnoty. Takéto riadky a stĺpce môžu zbytočne komplikovať analýzu a vizualizácie.
Na odstránenie prázdnych riadkov a stĺpcov môžeme použiť funkciu remove_empty()
.
<- data.frame(v1 = c(1, NA, 3),
q v2 = c(NA, NA, NA),
v3 = c("a", NA, "b"))
%>%
q remove_empty(c("rows", "cols"))
v1 v3
1 1 a
3 3 b
#> v1 v3
#> 1 1 a
#> 3 3 b
V niektorých dátových súboroch sa môžeme stretnúť so stĺpcami, ktoré odstraňujú len jednu hodnotu vo všetkých riadkoch. Takéto stĺpce zvyčajne neposkytujú žiadnu informatívnu hodnotu a môžu zbytočne zaťažovať analýzu.
Na ich odstránenie môžeme využiť funkciu remove_constant()
. Táto funkcia tiež umožňuje nastaviť, či sa majú považovať hodnoty NA
za odlišné od konštanty prostredníctvom parametra na.rm
. Funkcia pracuje nielen s data.frames, ale aj s maticami.
<- data.frame(good = 1:3, boring = "the same")
a %>% remove_constant() a
good
1 1
2 2
3 3
#> good
#> 1 1
#> 2 2
#> 3 3
V R sa štandartne používa tzv. “bankers rounding”, čo znamená, že polovičné hodnoty (napr. 2.5, 3.5) sa zaokrúhľujú na najbližšie párne číslo. V praxi to môže byť mätúce, keď očakávame, že 2.5 sa zaokrúhli nahor na 3.
Funkcia round_half_up()
rieši tento problém tým, že všetky polovičné hodnoty zaokrúhľuje nahor - presne podľa bežného očakávania.
<- c(2.5, 3.5)
nums round(nums)
[1] 2 4
#> [1] 2 4
round_half_up(nums)
[1] 3 4
#> [1] 3 4
Pri práci s dátami z Excelu sa často stretávame s číslami, ktoré predstavujú dátumy - napríklad hodnota 42223
by mala byť dátumom. Funkcia excel_numeric_to_date()
umožňuje tieto Excel serial numbers previesť na objekt triedy Date
alebo POSIXlt
, pričom podporuje rôzne systémy kódovania dátumov v Exceli a zachováva aj časové zložky ak sú obsiahnuté v zlomkoch dňa.
excel_numeric_to_date(41103)
[1] "2012-07-13"
#> [1] "2012-07-13"
excel_numeric_to_date(41103.01) # ignores decimal places, returns Date object
[1] "2012-07-13"
#> [1] "2012-07-13"
excel_numeric_to_date(41103.01, include_time = TRUE) # returns POSIXlt object
[1] "2012-07-13 00:14:24 CEST"
#> [1] "2012-07-13 00:14:24 EDT"
excel_numeric_to_date(41103.01, date_system = "mac pre-2011")
[1] "2016-07-14"
#> [1] "2016-07-14"
Takáto konverzia je užitočná, keď načítavame Excel súbory do R a chceme pracovať s dátumami priamo ako s dátovými typmi, namiesto manuálneho prevodu alebo zložitej úpravy čísel.
Funkcie convert_to_date()
a covert_to_datetime()
nadväzujú na excel_numeric_to_date()
a umožňujú robustnejšie spracovanie zmiešaných vstupov - napr. kombinácie textových dátumov a Excel serial numbers. Sú veľmi užitočné, keď načítavame viacero tabuliek, ktoré by mali mať rovnaké formáty stĺpcov, ale v praxi sa líšia.
convert_to_date(c("2020-02-29", "40000.1"))
[1] "2020-02-29" "2009-07-06"
#> [1] "2020-02-29" "2009-07-06"
convert_to_datetime(44874.5)
[1] "2022-11-09 12:00:00 UTC"
#> [1] "2022-11-09 12:00:00 UTC"
Očistime dáta v Titanic datasete, ktorý obsahuje informácie o pasažiaroch Titanicu. Tento dataset je verejne dostupný a využívaný napr. na riešenie klasifikačných problémov. Tento dataset obsahuje nejednotné názvy stĺpcov, napr. “PassengerId a”Name”, ktoré je potrebné upraviť.
library(janitor)
<- "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
url <- read.csv(url)
df
head(df)
PassengerId Survived Pclass
1 1 0 3
2 2 1 1
3 3 1 3
4 4 1 1
5 5 0 3
6 6 0 3
Name Sex Age SibSp Parch
1 Braund, Mr. Owen Harris male 22 1 0
2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female 38 1 0
3 Heikkinen, Miss. Laina female 26 0 0
4 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0
5 Allen, Mr. William Henry male 35 0 0
6 Moran, Mr. James male NA 0 0
Ticket Fare Cabin Embarked
1 A/5 21171 7.2500 S
2 PC 17599 71.2833 C85 C
3 STON/O2. 3101282 7.9250 S
4 113803 53.1000 C123 S
5 373450 8.0500 S
6 330877 8.4583 Q