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.

  • 🔎 Esimene tuvastamine: colSums(is.na(df)) loendab puuduvad väärtused veeru kohta enne nende käsitlemise kohta otsuse tegemist.
  • 🗑️ Rea eemaldamine: na.omit() eemaldab kõik NA-d sisaldavad read, kärpides Titanicu andmed 1,309 realt 1,045-le.
  • 📐 Keskmine imputeerimine: apply() koos na.rm = TRUE arvutab veeru keskmise ja mutate() koos ifelse() kirjutab selle uude veergu.
  • 📊 Mediaanalternatiiv: Mediaan tõrjub kõrvalekaldeid, mis teeb sellest turvalisema valiku viltunete muutujate, näiteks piletihinna puhul.
  • Massiline imputeerimine: apply() või across() rakendab sama reeglit igale numbrilisele veerule ühes lauses.
  • ⚠️ Teadaolev kompromiss: Keskmise imputeerimine vähendab dispersiooni ja nõrgestab korrelatsioone, seega ei tohiks seda kunagi pimesi rakendada.

Asenda puuduvad väärtused NA R-is

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.

Asenda R-s puuduvad väärtused

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.

Välista puuduvad väärtused

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:

Arvuta puuduvad andmed keskmise ja mediaaniga

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

KKK

NA tähistab vektori sees puuduvat väärtust. NULL tähistab objekti puudumist ja selle pikkus on null. NaN on määratlemata numbrilise tehte, näiteks nulli jagamise nulliga, tulemus.

Kasutage mediaani kaldus muutujate, näiteks piletihinna või sissetuleku puhul, sest erandid lohistavad keskmist ülespoole. Kasutage keskmist ainult siis, kui veerg on ligikaudu sümmeetriline ja äärmuslikest väärtustest vaba.

Iga tühimiku täitmine sama väärtusega vähendab veeru dispersiooni ja nõrgestab selle korrelatsiooni teiste muutujatega. Mudelipõhised meetodid, näiteks mice'i pakett, säilitavad neid seoseid palju paremini.

Enamik algoritme ei aktsepteeri nullväärtusi (NA) ning annab vea või jätab ridu märkamatult ära. Hooletu imputeerimine lekib teavet treening- ja testkomplektide vahel, seega arvutage imputeerimisväärtused alati ainult treeningjaotuse põhjal.

Jah. Tehisintellekti assistendid saavad puuduvate andmete mustri põhjal meetodeid soovitada ja dplyr-koodi mustandit koostada. Kontrollige valikut oma colSums(is.na()) väljundi ja valdkonna teadmiste põhjal, miks andmed puuduvad.

Võta see postitus kokku järgmiselt: