R में गुम मान (NA) को कैसे बदलें: na.omit & na.rm

⚡ स्मार्ट सारांश

R में गुमशुदा मानों को बदलना (Replace Missing Values ​​in R) पाठ्यक्रम में NA मानों का पता लगाना, na.omit() का उपयोग करके अपूर्ण पंक्तियों को हटाना और mutate() के माध्यम से उन्हें माध्य या माध्यिका से भरना शामिल है। इस पाठ्यक्रम में टाइटैनिक डेटासेट का उपयोग किया गया है, जिसमें आयु और किराया दोनों में गुमशुदा अवलोकन हैं।

  • 🔎 पहले पता लगाना: colSums(is.na(df)) कॉलम में गुम मानों की गणना करता है, इससे पहले कि यह तय किया जाए कि उन्हें कैसे संभाला जाए।
  • पंक्ति हटाना: na.omit() उन सभी पंक्तियों को हटा देता है जिनमें NA मान होता है, जिससे टाइटैनिक का डेटा 1,309 पंक्तियों से घटकर 1,045 पंक्तियों तक सीमित हो जाता है।
  • 📐 औसत आरोपण: apply() फ़ंक्शन का उपयोग करते समय na.rm = TRUE होने पर कॉलम का औसत निकाला जाता है, और mutate() फ़ंक्शन का उपयोग करते समय ifelse() होने पर इसे एक नए कॉलम में लिखा जाता है।
  • 📊 मध्य विकल्प: माध्यिका असामान्य मानों का प्रतिरोध करती है, जो इसे किराए जैसे विषम चरों के लिए एक सुरक्षित विकल्प बनाती है।
  • बल्क इम्पुटेशन: sapply() या across() एक ही स्टेटमेंट में प्रत्येक न्यूमेरिक कॉलम पर एक ही नियम लागू करते हैं।
  • ⚠️ ज्ञात समझौता: माध्य अनुमान विचरण को कम करता है और सहसंबंधों को कमजोर करता है, इसलिए इसे कभी भी अंधाधुंध रूप से लागू नहीं किया जाना चाहिए।

R में लुप्त मानों (NA) को बदलें

R में मिसिंग वैल्यू क्या होती हैं?

किसी कॉलम में कोई मान दर्ज न होने पर या संख्या के स्थान पर गैर-संख्यात्मक प्लेसहोल्डर होने पर लुप्त मान दिखाई देते हैं। किसी भी गणना से पहले इन्हें हटाना या बदलना आवश्यक है, क्योंकि R के अधिकांश फ़ंक्शन इनके मौजूद होते ही NA मान लौटाते हैं।

यह ट्यूटोरियल दिखाता है कि डेटा विश्लेषण के लिए टाइडीवर्स इकोसिस्टम का हिस्सा, डीप्लायर लाइब्रेरी का उपयोग करके गुम मानों को कैसे संभाला जाए।

R में लुप्त मानों को प्रतिस्थापित करें

पहला कदम हमेशा यह पता लगाना होता है कि कितने मान गायब हैं और कहाँ हैं।

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

प्लेसहोल्डर्स के बारे में एक चेतावनी। 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 है। उन स्तंभों का उपयोग करने वाला इम्पुटेशन इसे अच्छी तरह से संभालता है।
  • एमएनएआर, लापता होना यादृच्छिक नहीं है। संभावना स्वयं अनदेखे मूल्य पर निर्भर करती है, उदाहरण के लिए उच्च आय वाले लोग अपनी आय बताने से इनकार करते हैं। कोई भी अनुमान विधि केवल डेटा के आधार पर इसे ठीक नहीं कर सकती, और गुम डेटा में ही महत्वपूर्ण जानकारी छिपी होती है जिसे चिह्नित कॉलम में दर्ज करना आवश्यक है।

इस ट्यूटोरियल में प्रयुक्त माध्य इम्पुटेशन, केवल MCAR और सरल MAR के अंतर्गत ही उचित है। फिर भी, इसकी एक ज्ञात कमी है: प्रत्येक रिक्त स्थान को एक ही संख्या से भरने से कॉलम का विचरण कम हो जाता है और अन्य सभी कारकों के साथ उसका सहसंबंध कमजोर हो जाता है। गंभीर कार्य के लिए, MICE पैकेज जैसे मॉडल-आधारित विधि का उपयोग करें, और हमेशा एक फ़्लैग कॉलम रखें जो यह दर्शाता हो कि किन मानों को इम्पुट किया गया है।

उत्परिवर्तित ()

mutate() है दुत्कार यह एक क्रिया है जो एक नया चर बनाती है या मौजूदा चर को ओवरराइट करती है, जिससे यह किसी कॉलम की साफ-सुथरी प्रतिलिपि बनाने के लिए एक स्वाभाविक उपकरण बन जाता है।

हम दो भागों में आगे बढ़ेंगे। हम सीखेंगे कि कैसे:

  • डेटा फ़्रेम से अनुपलब्ध मानों को बाहर निकालें
  • माध्य और मध्यिका के साथ लुप्त मानों को आरोपित करें

क्रिया 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) को शामिल न करें

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 वाले कॉलम का माध्य निकालने के लिए apply विधि का उपयोग करेंगे। आइए एक उदाहरण देखें

चरण 1) ट्यूटोरियल में पहले हमने कॉलम के नाम को लिस्ट_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 स्पष्टीकरण:

हम apply विधि में 4 तर्क पास करते हैं।

  • df: df_titanic[,colnames(df_titanic) %in% list_na]. यह कोड list_na ऑब्जेक्ट से कॉलम का नाम लौटाएगा (यानी “आयु” और “किराया”)
  • 2: कॉलम पर फ़ंक्शन की गणना करें
  • माध्य: माध्य की गणना करें
  • na.rm = सत्य: लुप्त मानों को अनदेखा करें

आउटपुट:

##      age     fare 
## 29.88113 33.29548

हमने लापता प्रेक्षणों वाले स्तंभों का माध्य सफलतापूर्वक बनाया है। इन दो मानों का उपयोग लापता प्रेक्षणों को प्रतिस्थापित करने के लिए किया जाएगा।

चरण 3) NA मान बदलें

dplyr लाइब्रेरी से क्रिया mutate एक नया चर बनाने में उपयोगी है। हम मूल कॉलम को बदलना नहीं चाहते हैं ताकि हम 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(आयु), औसत_अनुपलब्ध[1], आयु)
  • replace_mean_fare = ifelse(is.na(किराया), औसत_लापता[2],किराया)

यदि कॉलम आयु में कोई मान गायब है, तो उसे average_missing (आयु का माध्य) के पहले तत्व से बदलें, अन्यथा मूल मान रखें। किराया के लिए भी यही तर्क लागू होता है

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)

माध्य या मध्यिका के साथ आरोपण दो तरीकों से किया जा सकता है

  • लागू करें का उपयोग करना
  • सैप्ली का उपयोग
विधि विवरण फायदे नुकसान
चरण दर चरण आवेदन करें लुप्त स्तंभों की जांच करें, माध्य/माध्यिका की गणना करें, मान संग्रहीत करें, mutate() से प्रतिस्थापित करें आप अनुमानित माध्य या माध्यिका देख सकते हैं। अधिक निष्पादन समय। बड़े डेटासेट के साथ धीमा हो सकता है
सैप्ली के साथ त्वरित तरीका sapply() और data.frame() का उपयोग करके स्वचालित रूप से लुप्त मानों को खोजें और उन्हें माध्य/माध्यिका से बदलें छोटा और तेज़ कोड अनुमानित मान कभी प्रदर्शित नहीं किए जाते हैं।

अक्सर पूछे जाने वाले प्रश्न

NA किसी वेक्टर में लुप्त मान को दर्शाता है। NULL किसी ऑब्जेक्ट की अनुपस्थिति को दर्शाता है और इसकी लंबाई शून्य होती है। NaN किसी अपरिभाषित संख्यात्मक संक्रिया का परिणाम है, जैसे शून्य को शून्य से भाग देना।

किराया या आय जैसे विषम चरों के लिए माध्यिका का प्रयोग करें, क्योंकि असामान्य मान माध्य को ऊपर की ओर खींचते हैं। माध्य का प्रयोग केवल तभी करें जब कॉलम लगभग सममित हो और उसमें कोई चरम मान न हो।

प्रत्येक रिक्त स्थान को एक ही मान से भरने से कॉलम का विचरण कम हो जाता है और अन्य चरों के साथ उसका सहसंबंध कमजोर हो जाता है। माइस पैकेज जैसे मॉडल-आधारित तरीके इन संबंधों को कहीं बेहतर ढंग से संरक्षित रखते हैं।

अधिकांश एल्गोरिदम NA मान स्वीकार नहीं कर सकते और त्रुटि उत्पन्न करेंगे या चुपचाप पंक्तियों को हटा देंगे। लापरवाही से की गई इम्पुटेशन से प्रशिक्षण और परीक्षण सेटों के बीच जानकारी लीक हो जाती है, इसलिए हमेशा इम्पुटेशन मानों की गणना केवल प्रशिक्षण विभाजन पर ही करें।

जी हां। एआई सहायक डेटा की अनुपलब्धता के पैटर्न के आधार पर विधियां सुझा सकते हैं और dplyr कोड तैयार कर सकते हैं। अपने colSums(is.na()) आउटपुट और डेटा की अनुपलब्धता के कारणों के बारे में अपने ज्ञान के आधार पर चुने गए विकल्प की पुष्टि करें।

इस पोस्ट को संक्षेप में इस प्रकार लिखें: