Kuidas asendada R-is puuduvad väärtused (NA): na.omit & na.rm
⚡ Nutikas kokkuvõte
R-i juhend „Puuduvate väärtuste asendamine” hõlmab NA väärtuste tuvastamist, mittetäielike ridade eemaldamist funktsiooniga na.omit() ja nendele keskmise või mediaani lisamist funktsiooni mutate() abil. See käsiraamat kasutab Titanicu andmestikku, kus nii vanus kui ka hind sisaldavad puuduvaid vaatlusi.

Millised on R-is puuduvad väärtused?
Puuduvad väärtused kuvatakse siis, kui vaatlusel pole veerus salvestatud väärtust või kui numbri asemel on mittenumbriline kohatäide. Need tuleb enne mis tahes arvutust eemaldada või asendada, sest enamik R-funktsioone tagastab NA (puuduvad väärtused) kohe, kui see esineb.
See õpetus näitab, kuidas käsitleda puuduvaid väärtusi dplyr teegiga, mis on osa andmeanalüüsi ökosüsteemist tidyverse.
Esimene samm on alati välja selgitada, mitu väärtust ja kust puudu on.
Kuidas tuvastada ja loendada puuduvaid väärtusi R-is
Enne puuduvate väärtustega tegelemise otsustamist peate teadma, kui palju neid on ja kus need asuvad. R pakub nelja kontrolli, alates ühest jah-või-ei vastusest kuni täieliku veerupõhise loendamiseni.
# 1. Is there any NA at all? anyNA(df_titanic) # 2. How many in total? sum(is.na(df_titanic)) # 3. How many per column, the most useful view colSums(is.na(df_titanic)) # 4. Percentage missing per column round(colMeans(is.na(df_titanic)) * 100, 1)
Praktikas on kõige parem kasutada funktsiooni colSums(). See tagastab nimetatud vektori, millel on igas veerus üks loendus, mis näitab kohe, kas muutujal puudub käputäis väärtusi või on see enamasti tühi.
Täisridade loendamine. complete.cases() tagastab TRUE väärtuse ridade puhul, millel pole ühtegi puuduvat väärtust, mis näitab ette, kui palju andmeid na.omit() eemaldaks:
sum(complete.cases(df_titanic)) # rows that would survive sum(!complete.cases(df_titanic)) # rows that would be dropped
Hoiatus kohahoidjate kohta. R tunneb ära ainult NA-d. Andmekogumid kodeerivad puuduvad väärtused sageli tühja stringina, tühikuna, „N/A“, „-“ või kontrollnumbrina, näiteks -99 või 999. Need läbivad kõik ülaltoodud kontrollid märkamatult. Teisendage need importimisel, et ülejäänud töövoog toimiks järgmiselt:
df <- read.csv(PATH, na.strings = c("", " ", "NA", "N/A", "-", "-99"))
Pärast importimist skannige alati iga numbrilise veeru vahemikku. Vanus -99 või hind 9999 on palju ohtlikum kui aus NA, sest ükski funktsioon ei hoiata teid selle eest.
Puuduvate andmete tüübid: MCAR, MAR ja MNAR
Väärtuse puudumise põhjus määrab, kas selle impulsseerimine on ohutu. Statistikud tunnevad ära kolm mehhanismi.
- MCAR, täiesti juhuslikult puudu. Kadumise tõenäosus ei ole seotud millegagi, olenemata sellest, kas seda vaadeldakse või mitte, näiteks anduri rike juhuslikel hetkedel.ping Või nende ridade imputeerimine ei too kaasa eelarvamust, vaid ainult täpsuse kadu.
- MAR, juhuslikult puudu. Tõenäosus sõltub teistest vaadeldud muutujatest, aga mitte puuduvast väärtusest endast. Kui vanemate reisijate vanuse registreerimise tõenäosus oli väiksem, siis on vanus teiste veergude põhjal MAR. Neid veerge kasutav imputeerimine lahendab selle probleemi hästi.
- MNAR, puudu mitte juhuslikult. Tõenäosus sõltub mittevaadeldavast väärtusest endast, näiteks kõrge sissetulekuga isikud keelduvad oma sissetulekut avaldamast. Ükski imputeerimismeetod ei suuda seda ainult andmete põhjal lahendada ja puudujääk ise sisaldab teavet, mida tasub lipukeerus kajastada.
Keskmise imputeerimine, nagu selles õpetuses kasutatud, on kaitstav ainult MCAR-i ja lihtsa MAR-i korral. Isegi siis on sellel teadaolev hind: iga lünga täitmine sama arvuga vähendab veeru dispersiooni ja nõrgestab selle korrelatsiooni kõige muuga. Tõsise töö jaoks kasutage mudelipõhist meetodit, näiteks mice'i paketti, ja hoidke alati lipukest veerus, mis tähistab imputeeritud väärtusi.
mute ()
mutate() on dplyr tegusõna, mis loob uue muutuja või kirjutab üle olemasoleva, mis teeb sellest loomuliku tööriista veeru puhastatud koopia loomiseks.
Jätkame kahes osas. Õpime, kuidas:
- välistada andmeraamist puuduvad väärtused
- arvutada puuduvad väärtused keskmise ja mediaaniga
Tegusõna mute() on väga lihtne kasutada. Saame luua uue muutuja, järgides seda süntaksit:
mutate(df, name_variable_1 = condition, ...) arguments: -df: Data frame used to create a new variable -name_variable_1: Name and the formula to create the new variable -...: No limit constraint. Possibility to create more than one variable inside mutate()
Puuduvate väärtuste välistamine (NA)
na.omit() on R-i baasfunktsioon, mitte dplyr-verb, aga see edastab kõik andmed puhtalt. See eemaldab iga rea, mis sisaldab vähemalt ühte NA-d. See on kiireim ja harva parim variant, sest üks puuduv väärtus eemaldab kogu vaatluse.
Puuduvate vaatluste probleemi lahendamiseks kasutame Titanicu andmekogumit. Selles andmekogumis on meil juurdepääs tragöödia ajal pardal viibinud reisijate teabele. Sellel andmekogumil on palju NA-sid, mille eest tuleb hoolt kanda.
Laadige internetist CSV-fail ja seejärel loetlege veerud, mis sisaldavad NA-d:
PATH <- "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/test.csv" df_titanic <- read.csv(PATH, sep = ",") # Return the column names containing missing observations list_na <- colnames(df_titanic)[ apply(df_titanic, 2, anyNA) ] list_na
Väljund:
## [1] "age" "fare"
Siin
colnames(df_titanic)[apply(df_titanic, 2, anyNA)]
tagastab veergude nimed, mis sisaldavad vähemalt ühte puuduvat väärtust.
Veergudel vanus ja piletihind puuduvad väärtused.
Saame need tühistada käsuga na.omit().
library(dplyr) # Exclude the missing observations df_titanic_drop <-df_titanic %>% na.omit() dim(df_titanic_drop)
Väljund:
## [1] 1045 13
Uus andmekogum sisaldab 1045 rida võrreldes 1309 reaga algse andmekogumiga.
Impulseeri puuduvad andmed keskmise ja mediaaniga
Samuti saate puuduvaid väärtusi imputeerida ehk täita keskmise või mediaaniga. Hea tava on luua keskmise ja mediaani jaoks kaks eraldi muutujat. Kui need on loodud, saame puuduvad väärtused asendada äsja moodustatud muutujatega.
Kasutame NA-ga veeru keskmise arvutamiseks rakendusmeetodit. Vaatame näidet
Step 1) Varasemas õpetuses salvestasime veergude nimed koos puuduvate väärtustega loendisse list_na. Kasutame seda nimekirja
Step 2) Arvuta keskmine argumendiga na.rm = TRUE. See argument on kohustuslik, kuna veergudel puuduvad andmed ja see käsib R-il neid ignoreerida.
# Create mean average_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, mean, na.rm = TRUE) average_missing
Code Selgitus:
Rakendusmeetodis edastame 4 argumenti.
- df: df_titanic[,colnames(df_titanic) %in% list_na]. See kood tagastab veergude nimed objektist list_na (st "vanus" ja "tariif")
- 2: arvutage veergude funktsioon
- keskmine: arvutage keskmine
- na.rm = TRUE: Ignoreeri puuduvaid väärtusi
Väljund:
## age fare ## 29.88113 33.29548
Oleme edukalt loonud puuduvaid vaatlusi sisaldavate veergude keskmise. Neid kahte väärtust kasutatakse puuduvate vaatluste asendamiseks.
Step 3) Asendage NA väärtused
Tegu dplyr teegist muteerima on kasulik uue muutuja loomisel. Me ei soovi tingimata algset veergu muuta, et saaksime luua uue muutuja ilma NA-ta. Mute on lihtne kasutada, me lihtsalt valime muutuja nime ja määratleme, kuidas seda muutujat luua. Siin on täielik kood
# Create a new variable with the mean and median df_titanic_replace <- df_titanic %>% mutate(replace_mean_age = ifelse(is.na(age), average_missing[1], age), replace_mean_fare = ifelse(is.na(fare), average_missing[2], fare))
Code Selgitus:
Loome kaks muutujat, asendada_keskmine_vanus ja asendada_keskmine_tariif järgmiselt:
- asenda_keskmine_vanus = ifelse(on.na(vanus), keskmine_puuduvad[1], vanus)
- asenda_keskmine_pilet = ifelse(on.na(pilet), keskmine_puudulik[2],pilet)
Kui veerus vanus puuduvad väärtused, asendage keskmise_puuduva (vanuse keskmine) elemendiga, vastasel juhul säilitage algsed väärtused. Sama loogika piletihinna osas
sum(is.na(df_titanic_replace$age))
Väljund:
## [1] 263
Pärast asendamist ei sisalda uus veerg ühtegi puuduvat väärtust:
sum(is.na(df_titanic_replace$replace_mean_age))
Väljund:
## [1] 0
Algses vanuse veerus on 263 puuduvat väärtust, samas kui uus replace_mean_age veerg on kõik need väärtused täitnud keskmise vanusega.
Step 4) Puuduvad vaatlused saame asendada ka mediaaniga.
median_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, median, na.rm = TRUE) df_titanic_replace <- df_titanic %>% mutate(replace_median_age = ifelse(is.na(age), median_missing[1], age), replace_median_fare = ifelse(is.na(fare), median_missing[2], fare)) head(df_titanic_replace)
Väljund:
Step 5) Suure andmestiku puhul muutub samm-sammult meetod tüütuks. sapply() koondab kogu protseduuri ühte lausesse, mille hinnaga imputeeritud väärtusi ei kuvata kunagi.
sapply ei loo a andmeraam, et saaksime andmeraami objekti loomiseks mähkida funktsiooni sapply() sisse data.frame().
# Quick code to replace missing values with the mean df_titanic_impute_mean <- data.frame( sapply( df_titanic, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x)))
Moodne imputeerimine funktsioonidega replace_na() ja across()
Ülaltoodud apply() ja sapply() meetodid toimivad endiselt, aga tidyr ja dplyr väljendavad samu operatsioone nüüd turvalisemalt ja loetavamalt.
replace_na() fikseeritud väärtuste korral. tidyr::replace_na() võtab nimetatud veergude loendi ja nende asendused:
library(tidyr) df_titanic %>% replace_na(list(age = 29.88, fare = 33.30))
across() iga numbrilise veeru jaoks. See on üherealise funktsiooni sapply() otsene ja tüübikindel asendus ning erinevalt funktsioonist sapply() ei puuduta see kunagi tähemärke ega tegureid:
library(dplyr) # Mean-impute every numeric column df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x))) # Median-impute instead df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), median(.x, na.rm = TRUE), .x)))
⚠️ Miks on otsetee sapply() riskantne: üherealine sapply() näide jookseb üle iga veerg, sealhulgas märgi- ja tegurveerg. Funktsiooni mean() kutsumine nende puhul tagastab väärtuse NA koos hoiatusega ja apply() teisendab seejärel kogu tulemuse märgiks. Ülaltoodud across(where(is.numeric), …) versioon väldib seda täielikult.
coalesce() varuveergude jaoks. Kui teine veerg suudab puuduva väärtuse anda, tagastab coalesce() oma argumentide põhjal esimese korrektse kirje:
df %>% mutate(age_final = coalesce(age, age_estimated, 0))
Jälgige, mida te muutsite. Lisa enne imputeerimist lipp, et hilisem mudel saaks õppida väärtuse puudumisest:
df_titanic %>%
mutate(age_was_missing = is.na(age),
age = ifelse(is.na(age), mean(age, na.rm = TRUE), age))
Puuduvate väärtuste käsitlemine R-is: meetodi viide
Selles õpetuses käsitletakse kolme lähenemisviisi:
- Välista kõik puuduvad tähelepanekud
- Arvuta keskmisega
- Arvestus mediaaniga
Allolev tabel võtab kokku tuvastamise ja eemaldamise:
| Raamatukogu | Eesmärk | Code |
|---|---|---|
| baas | Loetlege puuduvad tähelepanekud |
colnames(df)[apply(df, 2, anyNA)] |
| baas | Eemalda iga rida, mis sisaldab NA-d |
na.omit(df) |
Arvutamist keskmise või mediaaniga saab teha kahel viisil
- Rakenduse kasutamine
- Sapply kasutamine
| Meetod | Detailid | Eelised | Puudused |
|---|---|---|---|
| Rakendamisega samm-sammult | Kontrollige puuduvaid veerge, arvutage keskmine/mediaan, salvestage väärtus, asendage käsuga mute() | Näete imputeeritud keskmist või mediaani | Rohkem täitmisaega. Suure andmestikuga võib see olla aeglane |
| Kiire viis sapplyga | Kasutage sapply() ja data.frame() puuduvate väärtuste automaatseks otsimiseks ja asendamiseks keskmise/mediaaniga | Lühikood ja kiire | Kaudseid väärtusi ei kuvata kunagi |



