Πώς να αντικαταστήσετε τις τιμές που λείπουν (NA) στο R: na.omit & na.rm
⚡ Έξυπνη Σύνοψη
Η Αντικατάσταση Λείποντων Τιμών στην R καλύπτει την ανίχνευση τιμών NA, την αφαίρεση ελλιπών γραμμών με na.omit() και την καταλογισμό τους στον μέσο όρο ή τη διάμεσο μέσω mutate(). Αυτή η αναλυτική παρουσίαση χρησιμοποιεί το σύνολο δεδομένων Titanic, όπου η ηλικία και το ναύλο φέρουν και οι δύο ελλείπουσες παρατηρήσεις.

Ποιες είναι οι τιμές που λείπουν στο R;
Οι τιμές που λείπουν εμφανίζονται όταν μια παρατήρηση δεν έχει καταγεγραμμένη τιμή σε μια στήλη ή όταν ένα μη αριθμητικό σύμβολο κράτησης θέσης βρίσκεται εκεί που θα έπρεπε να βρίσκεται ένας αριθμός. Πρέπει να αφαιρεθούν ή να αντικατασταθούν πριν από οποιονδήποτε υπολογισμό, επειδή οι περισσότερες συναρτήσεις R επιστρέφουν NA τη στιγμή που υπάρχει μία.
Αυτό το σεμινάριο δείχνει πώς να χειρίζεστε τιμές που λείπουν με τη βιβλιοθήκη dplyr, μέρος του οικοσυστήματος tidyverse για ανάλυση δεδομένων.
Το πρώτο βήμα είναι πάντα να ανακαλύψετε πόσες τιμές λείπουν και πού.
Πώς να εντοπίσετε και να μετρήσετε ελλείπουσες τιμές στο R
Πριν αποφασίσετε τι να κάνετε σχετικά με τις τιμές που λείπουν, πρέπει να γνωρίζετε πόσες υπάρχουν και πού βρίσκονται. Η R προσφέρει τέσσερις ελέγχους, από μία μόνο απάντηση ναι ή όχι έως μια πλήρη καταμέτρηση ανά στήλη.
# 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)
Η συνάρτηση colSums() είναι αυτή που πρέπει να χρησιμοποιούμε στην πράξη. Επιστρέφει ένα ονομασμένο διάνυσμα με μία καταμέτρηση ανά στήλη, η οποία δείχνει αμέσως εάν μια μεταβλητή δεν έχει αρκετές τιμές ή είναι ως επί το πλείστον κενή.
Μέτρηση πλήρων γραμμών. Η complete.cases() επιστρέφει TRUE για γραμμές χωρίς καμία τιμή πουθενά, η οποία σας λέει εκ των προτέρων πόσα δεδομένα θα απορρίψει η na.omit():
sum(complete.cases(df_titanic)) # rows that would survive sum(!complete.cases(df_titanic)) # rows that would be dropped
Μια προειδοποίηση σχετικά με τα placeholder. Η R αναγνωρίζει μόνο NA. Τα σύνολα δεδομένων συχνά κωδικοποιούν τιμές που λείπουν ως κενή συμβολοσειρά, κενό, "N/A", "-" ή αριθμό φρουρού όπως -99 ή 999. Αυτά περνούν κάθε παραπάνω έλεγχο απαρατήρητα. Μετατρέψτε τα κατά την εισαγωγή, ώστε η υπόλοιπη ροή εργασίας να συμπεριφέρεται ως εξής:
df <- read.csv(PATH, na.strings = c("", " ", "NA", "N/A", "-", "-99"))
Να σαρώνετε πάντα το εύρος κάθε αριθμητικής στήλης μετά την εισαγωγή. Μια ηλικία -99 ή ένα ναύλο 9999 είναι πολύ πιο επικίνδυνα από μια ειλικρινή NA, επειδή καμία συνάρτηση δεν θα σας προειδοποιήσει γι' αυτό.
Τύποι ελλειπόντων δεδομένων: MCAR, MAR και MNAR
Το γιατί λείπει μια τιμή καθορίζει εάν η καταλογισμό της είναι ασφαλής. Οι στατιστικολόγοι αναγνωρίζουν τρεις μηχανισμούς.
- MCAR, λείπει εντελώς τυχαία. Η πιθανότητα να λείπει δεν σχετίζεται με τίποτα, παρατηρούμενο ή όχι, για παράδειγμα έναν αισθητήρα που παρουσιάζει βλάβη σε τυχαίες στιγμές.ping ή η καταλογισμό αυτών των γραμμών δεν εισάγει καμία μεροληψία, μόνο απώλεια ακρίβειας.
- ΜΑΡ, λείπει τυχαία. Η πιθανότητα εξαρτάται από άλλες παρατηρούμενες μεταβλητές, αλλά όχι από την ίδια την τιμή που λείπει. Εάν οι ηλικιωμένοι επιβάτες είχαν λιγότερες πιθανότητες να καταγραφεί η ηλικία τους, η ηλικία είναι MAR δεδομένων των άλλων στηλών. Η συμπλήρωση που χρησιμοποιεί αυτές τις στήλες χειρίζεται καλά αυτό το πρόβλημα.
- MNAR, δεν λείπει τυχαία. Η πιθανότητα εξαρτάται από την ίδια την μη παρατηρούμενη τιμή, για παράδειγμα άτομα με υψηλά εισοδήματα που αρνούνται να δηλώσουν το εισόδημά τους. Καμία μέθοδος καταλογισμού δεν μπορεί να διορθώσει αυτό το πρόβλημα από μόνη της με βάση τα δεδομένα και η ίδια η έλλειψη περιέχει πληροφορίες που αξίζει να καταγραφούν σε μια στήλη με σημαία.
Η καταλογισμός μέσου όρου, όπως χρησιμοποιείται σε αυτό το σεμινάριο, είναι δικαιολογημένη μόνο υπό MCAR και απλή MAR. Ακόμα και τότε έχει ένα γνωστό κόστος: η συμπλήρωση κάθε κενού με τον ίδιο αριθμό συρρικνώνει τη διακύμανση της στήλης και αποδυναμώνει τη συσχέτισή της με όλα τα άλλα. Για σοβαρή εργασία, χρησιμοποιήστε μια μέθοδο που βασίζεται σε μοντέλο, όπως το πακέτο mices, και να διατηρείτε πάντα μια στήλη με σημαία που να επισημαίνει ποιες τιμές καταλογίστηκαν.
αλλάσσω()
Η mutate() είναι η dplyr ρήμα που δημιουργεί μια νέα μεταβλητή ή αντικαθιστά μια υπάρχουσα, γεγονός που το καθιστά το φυσικό εργαλείο για τη δημιουργία ενός καθαρισμένου αντιγράφου μιας στήλης.
Θα προχωρήσουμε σε δύο μέρη. Θα μάθουμε πώς να:
- εξαιρέσει τις τιμές που λείπουν από ένα πλαίσιο δεδομένων
- υπολογίστε τιμές που λείπουν με τη μέση και τη διάμεσο
Το ρήμα mutate() είναι πολύ εύκολο στη χρήση. Μπορούμε να δημιουργήσουμε μια νέα μεταβλητή ακολουθώντας αυτή τη σύνταξη:
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()
Εξαίρεση τιμών που λείπουν (ΔΕ)
Η na.omit() είναι μια βασική συνάρτηση R, όχι ένα ρήμα dplyr, αλλά εκτελείται με ακρίβεια. Διαγράφει κάθε γραμμή που περιέχει τουλάχιστον ένα NA. Αυτή είναι η πιο γρήγορη επιλογή και σπάνια η καλύτερη, επειδή μια μεμονωμένη τιμή που λείπει απορρίπτει ολόκληρη την παρατήρηση.
Για να αντιμετωπίσουμε το πρόβλημα των παρατηρήσεων που λείπουν, θα χρησιμοποιήσουμε το τιτανικό σύνολο δεδομένων. Σε αυτό το σύνολο δεδομένων, έχουμε πρόσβαση στις πληροφορίες των επιβατών κατά τη διάρκεια της τραγωδίας. Αυτό το σύνολο δεδομένων έχει πολλά NA που πρέπει να ληφθούν υπόψη.
Φορτώστε το αρχείο CSV από το διαδίκτυο και, στη συνέχεια, παραθέστε τις στήλες που περιέχουν NA:
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
Παραγωγή:
## [1] "age" "fare"
Εδώ,
colnames(df_titanic)[apply(df_titanic, 2, anyNA)]
Επιστρέφει τα ονόματα των στηλών που περιέχουν τουλάχιστον μία τιμή που λείπει.
Οι στήλες ηλικία και ναύλος έχουν τιμές που λείπουν.
Μπορούμε να τα ρίξουμε με το na.omit().
library(dplyr) # Exclude the missing observations df_titanic_drop <-df_titanic %>% na.omit() dim(df_titanic_drop)
Παραγωγή:
## [1] 1045 13
Το νέο σύνολο δεδομένων περιέχει 1045 σειρές σε σύγκριση με 1309 με το αρχικό σύνολο δεδομένων.
Υπολογίστε τα ελλείποντα δεδομένα με τον μέσο όρο και τη διάμεσο
Μπορείτε επίσης να υπολογίσετε, δηλαδή να συμπληρώσετε, τις τιμές που λείπουν με τον μέσο όρο ή τη διάμεσο. Μια καλή πρακτική είναι να δημιουργήσετε δύο ξεχωριστές μεταβλητές για τον μέσο όρο και τη διάμεσο. Μόλις δημιουργηθούν, μπορούμε να αντικαταστήσουμε τις τιμές που λείπουν με τις νεοσχηματισμένες μεταβλητές.
Θα χρησιμοποιήσουμε τη μέθοδο εφαρμογής για να υπολογίσουμε τη μέση τιμή της στήλης με NA. Ας δούμε ένα παράδειγμα
Βήμα 1) Νωρίτερα στο σεμινάριο, αποθηκεύσαμε το όνομα στηλών με τις τιμές που λείπουν στη λίστα που ονομάζεται list_na. Θα χρησιμοποιήσουμε αυτή τη λίστα
Βήμα 2) Υπολογίστε τον μέσο όρο με το όρισμα na.rm = TRUE. Αυτό το όρισμα είναι υποχρεωτικό επειδή οι στήλες έχουν δεδομένα που λείπουν και αυτό λέει στην R να τα αγνοήσει.
# Create mean average_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, mean, na.rm = TRUE) average_missing
Code Επεξήγηση:
Περνάμε 4 ορίσματα στη μέθοδο εφαρμογής.
- df: df_titanic[,colnames(df_titanic) %in% list_na]. Αυτός ο κωδικός θα επιστρέψει το όνομα στηλών από το αντικείμενο list_na (π.χ. "ηλικία" και "ναύλος")
- 2: Υπολογίστε τη συνάρτηση στις στήλες
- μέσος όρος: Υπολογίστε τον μέσο όρο
- na.rm = TRUE: Αγνοήστε τις τιμές που λείπουν
Παραγωγή:
## age fare ## 29.88113 33.29548
Δημιουργήσαμε με επιτυχία τον μέσο όρο των στηλών που περιέχουν παρατηρήσεις που λείπουν. Αυτές οι δύο τιμές θα χρησιμοποιηθούν για την αντικατάσταση των παρατηρήσεων που λείπουν.
Βήμα 3) Αντικαταστήστε τις τιμές NA
Το ρήμα mutate από τη βιβλιοθήκη dplyr είναι χρήσιμο για τη δημιουργία μιας νέας μεταβλητής. Δεν θέλουμε απαραίτητα να αλλάξουμε την αρχική στήλη, ώστε να μπορούμε να δημιουργήσουμε μια νέα μεταβλητή χωρίς το NA. Το mutate είναι εύκολο στη χρήση, απλώς επιλέγουμε ένα όνομα μεταβλητής και ορίζουμε τον τρόπο δημιουργίας αυτής της μεταβλητής. Εδώ είναι ο πλήρης κώδικας
# 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 Επεξήγηση:
Δημιουργούμε δύο μεταβλητές, replace_mean_age και replace_mean_fare ως εξής:
- replace_mean_age = ifelse(is.na(ηλικία), average_missing[1], ηλικία)
- replace_mean_fare = ifelse(is.na(ναύλος), average_missing[2],ναύλος)
Εάν η ηλικία της στήλης έχει τιμές που λείπουν, αντικαταστήστε το με το πρώτο στοιχείο του μέσου όρου_λείπει (μέσος όρος ηλικίας), διαφορετικά διατηρήστε τις αρχικές τιμές. Ίδια λογική για ναύλο
sum(is.na(df_titanic_replace$age))
Παραγωγή:
## [1] 263
Μετά την αντικατάσταση, η νέα στήλη δεν περιέχει καθόλου τιμές που λείπουν:
sum(is.na(df_titanic_replace$replace_mean_age))
Παραγωγή:
## [1] 0
Η αρχική στήλη ηλικίας περιέχει 263 τιμές που λείπουν, ενώ η νέα στήλη replace_mean_age έχει συμπληρώσει κάθε μία από αυτές με τη μέση ηλικία.
Βήμα 4) Μπορούμε να αντικαταστήσουμε τις παρατηρήσεις που λείπουν με τη διάμεσο επίσης.
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)
Παραγωγή:
Βήμα 5) Σε ένα ευρύ σύνολο δεδομένων, η μέθοδος βήμα προς βήμα γίνεται κουραστική. Η sapply() συμπτύσσει ολόκληρη τη διαδικασία σε μία εντολή, με κόστος να μην εμφανίζονται ποτέ οι τιμές που έχουν εισαχθεί.
sapply δεν δημιουργεί α πλαίσιο δεδομένων, έτσι μπορούμε να τυλίξουμε τη συνάρτηση sapply() μέσα στο 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)))
Σύγχρονος Υπολογισμός με replace_na() και across()
Οι παραπάνω προσεγγίσεις apply() και sapply() εξακολουθούν να λειτουργούν, αλλά οι tidyr και dplyr εκφράζουν πλέον τις ίδιες λειτουργίες με μεγαλύτερη ασφάλεια και ευκρίνεια.
replace_na() για σταθερές τιμές. Η tidyr::replace_na() δέχεται μια ονομαστική λίστα στηλών και τις αντικαταστάσεις τους:
library(tidyr) df_titanic %>% replace_na(list(age = 29.88, fare = 33.30))
across() για κάθε αριθμητική στήλη. Αυτή είναι η άμεση, ασφαλής για τύπους αντικατάσταση της μονογραμμικής συνάρτησης sapply() και, σε αντίθεση με τη συνάρτηση sapply(), δεν αγγίζει ποτέ στήλες χαρακτήρων ή παραγόντων:
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)))
⚠️ Γιατί η συντόμευση sapply() είναι επικίνδυνη: το παράδειγμα sapply() μιας γραμμής εκτελείται πάνω από κάθε στήλη, συμπεριλαμβανομένων των χαρακτήρων και των παραγόντων. Η κλήση της mean() σε αυτές τις στήλες επιστρέφει NA με μια προειδοποίηση, και η sapply() στη συνέχεια μετατρέπει ολόκληρο το αποτέλεσμα σε χαρακτήρα. Η έκδοση across(where(is.numeric), …) παραπάνω αποφεύγει αυτό εντελώς.
coalesce() για εφεδρικές στήλες. Όταν μια δεύτερη στήλη μπορεί να παρέχει την τιμή που λείπει, η συνάρτηση coalesce() επιστρέφει την πρώτη καταχώρηση που δεν λείπει στα ορίσματά της:
df %>% mutate(age_final = coalesce(age, age_estimated, 0))
Κρατήστε ένα αρχείο με ό,τι αλλάξατε. Προσθέστε μια σημαία πριν από την καταχώρηση, ώστε οποιοδήποτε μεταγενέστερο μοντέλο να μπορεί να μάθει από το γεγονός ότι έλειπε μια τιμή:
df_titanic %>%
mutate(age_was_missing = is.na(age),
age = ifelse(is.na(age), mean(age, na.rm = TRUE), age))
Χειρισμός ελλειπουσών τιμών στην R: Αναφορά μεθόδου
Σε αυτό το σεμινάριο καλύπτονται τρεις προσεγγίσεις:
- Εξαιρέστε όλες τις παρατηρήσεις που λείπουν
- Καταλογισμός με το μέσο όρο
- Καταλογισμός με τη διάμεσο
Ο παρακάτω πίνακας συνοψίζει την ανίχνευση και την αφαίρεση:
| Βιβλιοθήκη | Σκοπός | Code |
|---|---|---|
| βάση | Κατάλογος παρατηρήσεων που λείπουν |
colnames(df)[apply(df, 2, anyNA)] |
| βάση | Αφαίρεση κάθε γραμμής που περιέχει NA |
na.omit(df) |
Ο καταλογισμός με μέσο όρο ή διάμεσο μπορεί να γίνει με δύο τρόπους
- Χρησιμοποιώντας την εφαρμογή
- Χρήση sapply
| Μέθοδος | Λεπτομέρειες | Πλεονεκτήματα | Μειονεκτήματα |
|---|---|---|---|
| Βήμα προς βήμα με την εφαρμογή | Ελέγξτε τις στήλες που λείπουν, υπολογίστε τη μέση/διάμεσο, αποθηκεύστε την τιμή, αντικαταστήστε με mutate() | Μπορείτε να δείτε τον υπολογιζόμενο μέσο όρο ή διάμεσο | Περισσότερος χρόνος εκτέλεσης. Μπορεί να είναι αργό με μεγάλο σύνολο δεδομένων |
| Γρήγορος τρόπος με αρμολόγηση | Χρησιμοποιήστε τα sapply() και data.frame() για αυτόματη αναζήτηση και αντικατάσταση τιμών που λείπουν με μέσο/διάμεσο | Σύντομος κωδικός και γρήγορος | Οι υπολογιζόμενες τιμές δεν εμφανίζονται ποτέ |



