केवल एनए वाले कॉलम को कैसे हटाएं?


83

मेरे पास सभी NA मानों के साथ कुछ कॉलम वाले डेटा.फ्रेम हैं, मैं उन्हें डेटा से कैसे हटा सकता हूं।

क्या मैं फ़ंक्शन का उपयोग कर सकता हूं

na.omit(...) 

कुछ अतिरिक्त तर्क निर्दिष्ट कर रहे हैं?


1
नमस्ते! कृपया अपने पोस्ट को प्रतिलिपि प्रस्तुत करने योग्य बनाएं। यह करने के लिए कैसे पर एक महान प्रतिलिपि प्रस्तुत करने योग्य उदाहरण बनाने के लिए पोस्ट पढ़ें । धन्यवाद।
अरुण

क्या यह पोस्ट मदद करती है? stackoverflow.com/questions/4862178/…
अरुण

क्या आप पोस्ट कर सकते हैं head(data)? क्या आप संबंधित कॉलम या पंक्तियों को हटाना चाहते हैं?
निशांत

@ e4e5f4 मैं इसी कॉलम को हटाना चाहता हूं (कॉलम के सभी मूल्य जिन्हें मैं हटाना चाहता हूं NA हैं)
लोरेंजो रिगामोंटी

जवाबों:


123

इसे करने का एक तरीका:

df[, colSums(is.na(df)) != nrow(df)]

यदि किसी कॉलम में NA की संख्या पंक्तियों की संख्या के बराबर है, तो यह पूरी तरह से NA होना चाहिए।

या इसी तरह

df[colSums(!is.na(df)) > 0]

1
मैं NA की सीमा से अधिक वाले कॉलम कैसे हटा सकता हूं? या प्रतिशत में (50% से ऊपर कहते हैं)?
शिष्य

2
@lovedynasty एक अलग प्रश्न प्रस्तुत करने के लिए संभवतः सबसे अच्छा है, यह मानते हुए कि आप अपनी टिप्पणी पोस्ट करने के बाद से पहले से ही नहीं हैं। लेकिन वैसे भी, आप हमेशा कुछ ऐसा कर सकते हैं df[, colSums(is.na(df)) < nrow(df) * 0.5]यानी केवल कम से कम 50% गैर-रिक्त कॉलम वाले कॉलम रखें।
मैडस्कॉन

2
एक सहसंबंध मैट्रिक्स के साथ काम करने वाले लोगों को उपयोग करना चाहिए df[, colSums(is.na(df)) != nrow(df) - 1]क्योंकि विकर्ण हमेशा होता है1
बोर्न

9
इस dplyr (संस्करण 0.5.0) select_if फ़ंक्शन के साथ भी उपयोग कर सकते हैं। df %>% select_if(colSums(!is.na(.)) > 0)
स्टीफन एवे

@MadScone यह मुझे "," df [, colSums (is.na (df))! = Nrow (df)] और "में सिंटैक्स त्रुटि" के लिए सिंटैक्स त्रुटि दे रहा है। df में [colSums (! is.na (df))> 0]। क्या मुझे कुछ याद आ रहा है
अरविंद एस

52

यहाँ एक dplyr समाधान है:

df %>% select_if(~sum(!is.na(.)) > 0)

4
~ 15k पंक्तियों और ~ 5k स्तंभों पर, यह वास्तव में हमेशा के लिए ले रहा है।
EngrStudent

@EngrStudent क्या यह स्वीकृत उत्तर के समाधान के साथ तेज़ था?
जॉनी

कई साल हो गए। मुझे याद नहीं है। DJV के नीचे एक अच्छा टाइमिंग पोस्ट है।
EngrStudent

25

एक अन्य विकल्प janitorपैकेज है:

df <- remove_empty_cols(df)

https://github.com/sfirke/janitor


10
janitor::remove_empty_cols()पदावनत किया जाता है - उपयोग करेंdf <- janitor::remove_empty(df, which = "cols")
André.B

24

यह देखता है कि आप ऑल एस के साथ केवल कॉलम को हटाना चाहते हैं , जो कुछ पंक्तियों के साथ कॉलम छोड़ रहे हैं । मैं यह करूँगा (लेकिन मुझे यकीन है कि एक कुशल सदिश सेना है: NANA

#set seed for reproducibility
set.seed <- 103
df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )
df
#      id nas vals
#   1   1  NA   NA
#   2   2  NA    2
#   3   3  NA    1
#   4   4  NA    2
#   5   5  NA    2
#   6   6  NA    3
#   7   7  NA    2
#   8   8  NA    3
#   9   9  NA    3
#   10 10  NA    2

#Use this command to remove columns that are entirely NA values, it will elave columns where only some vlaues are NA
df[ , ! apply( df , 2 , function(x) all(is.na(x)) ) ]
#      id vals
#   1   1   NA
#   2   2    2
#   3   3    1
#   4   4    2
#   5   5    2
#   6   6    3
#   7   7    2
#   8   8    3
#   9   9    3
#   10 10    2

यदि आप अपने आप को उस स्थिति में पाते हैं जहाँ आप ऐसे कॉलम हटाना चाहते हैं जिनमें कोई भी NAमूल्य हो तो आप बस allऊपर दिए गए कमांड को बदल सकते हैं any


डेटा.फ्रेम में दो प्रकार के कॉलम होते हैं: एक है जिसके सभी मान संख्याएँ हैं और दूसरे जिसमें सभी मान NA हैं
लोरेंजो रिगामोंटी

तो यह तब काम करेगा। यह केवल कॉलम निकालता है सभी मान थे NA
साइमन ओ'हलान 2

1
अच्छा समाधान। apply(is.na(df), 1, all)हालांकि मैं सिर्फ इसलिए करूंगा क्योंकि यह थोड़ा नटखट है और एक समय में एक पंक्ति is.na()के dfबजाय सभी पर उपयोग किया जाता है (शो थोड़ा तेज हो)।
MadScone

@MadScone अच्छा टिप - नटखट दिखता है। आपको स्तंभों पर पंक्तियों पर लागू होना चाहिए, हालांकि पंक्तियों में नहीं।
साइमन ओ'हलान 2

@MadScone संपादन टिप्पणियों पर 5 मिनट के बाद बंद कर दिया जाता है। मुझे चिंता नहीं करनी चाहिए, यह कोई बड़ी बात नहीं है !! :-)
साइमन ओ'हलान 2

19

एक सहज ज्ञान युक्त स्क्रिप्ट dplyr::select_if(~!all(is.na(.))):। यह शाब्दिक रूप से केवल सभी-तत्वों-लापता कॉलम को नहीं रखता है। (सभी-तत्व-अनुपलब्ध स्तंभों को हटाने के लिए)।

> df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )

> df %>% glimpse()
Observations: 10
Variables: 3
$ id   <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
$ nas  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
$ vals <int> NA, 1, 1, NA, 1, 1, 1, 2, 3, NA

> df %>% select_if(~!all(is.na(.))) 
   id vals
1   1   NA
2   2    1
3   3    1
4   4   NA
5   5    1
6   6    1
7   7    1
8   8    2
9   9    3
10 10   NA

17

के साथ एक और विकल्प Filter

Filter(function(x) !all(is.na(x)), df)

नोट: @Simon O'Hanlon के पोस्ट से डेटा।


5

क्योंकि प्रदर्शन वास्तव में मेरे लिए महत्वपूर्ण था, मैंने उपरोक्त सभी कार्यों को बेंचमार्क किया।

नोट: @Simon O'Hanlon के पोस्ट से डेटा। केवल 10 के बजाय आकार 15000 के साथ।

library(tidyverse)
library(microbenchmark)

set.seed(123)
df <- data.frame(id = 1:15000,
                 nas = rep(NA, 15000), 
                 vals = sample(c(1:3, NA), 15000,
                               repl = TRUE))
df

MadSconeF1 <- function(x) x[, colSums(is.na(x)) != nrow(x)]

MadSconeF2 <- function(x) x[colSums(!is.na(x)) > 0]

BradCannell <- function(x) x %>% select_if(~sum(!is.na(.)) > 0)

SimonOHanlon <- function(x) x[ , !apply(x, 2 ,function(y) all(is.na(y)))]

jsta <- function(x) janitor::remove_empty(x)

SiboJiang <- function(x) x %>% dplyr::select_if(~!all(is.na(.)))

akrun <- function(x) Filter(function(y) !all(is.na(y)), x)

mbm <- microbenchmark(
  "MadSconeF1" = {MadSconeF1(df)},
  "MadSconeF2" = {MadSconeF2(df)},
  "BradCannell" = {BradCannell(df)},
  "SimonOHanlon" = {SimonOHanlon(df)},
  "SiboJiang" = {SiboJiang(df)},
  "jsta" = {jsta(df)}, 
  "akrun" = {akrun(df)},
  times = 1000)

mbm

परिणाम:

Unit: microseconds
         expr    min      lq      mean  median      uq      max neval  cld
   MadSconeF1  154.5  178.35  257.9396  196.05  219.25   5001.0  1000 a   
   MadSconeF2  180.4  209.75  281.2541  226.40  251.05   6322.1  1000 a   
  BradCannell 2579.4 2884.90 3330.3700 3059.45 3379.30  33667.3  1000    d
 SimonOHanlon  511.0  565.00  943.3089  586.45  623.65 210338.4  1000  b  
    SiboJiang 2558.1 2853.05 3377.6702 3010.30 3310.00  89718.0  1000    d
         jsta 1544.8 1652.45 2031.5065 1706.05 1872.65  11594.9  1000   c 
        akrun   93.8  111.60  139.9482  121.90  135.45   3851.2  1000 a


autoplot(mbm)

यहाँ छवि विवरण दर्ज करें

mbm %>% 
  tbl_df() %>%
  ggplot(aes(sample = time)) + 
  stat_qq() + 
  stat_qq_line() +
  facet_wrap(~expr, scales = "free")

यहाँ छवि विवरण दर्ज करें


कभी-कभी पहला पुनरावृत्ति एक जेआईटी संकलित होता है, इसलिए यह बहुत खराब है, और बहुत विशेषता नहीं है, समय। मुझे लगता है कि यह दिलचस्प है कि बड़ा नमूना आकार वितरण की सही पूंछ को क्या करता है। यह अच्छा काम है।
EngrStudent

मैंने इसे एक बार फिर से चलाया, मुझे यकीन नहीं था कि मैंने साजिश को बदल दिया है। वितरण के संबंध में, वास्तव में। जब मेरे पास समय होगा तो मुझे अलग-अलग नमूने के आकारों की तुलना करनी चाहिए।
डीजेवी

1
अगर आप qqplot ( ggplot2.tidyverse.org/reference/geom_qq.html ) में से एक ट्रेंड, जैसे कि "एकरुन" तो मैं शर्त लगाता हूं कि एक बिंदु ऐसा है जो बाकी के वितरण से बहुत अलग है। बाकी प्रतिनिधित्व करते हैं कि अगर आप इसे बार-बार चलाते हैं, तो कितना समय लगता है, लेकिन अगर आप इसे एक बार चलाते हैं तो क्या होता है। एक पुरानी कहावत है: आपके पास 20 साल का अनुभव हो सकता है या आपके पास केवल एक साल का अनुभव 20 गुना हो सकता है।
EngrStudent

बहुत अच्छा! मैं कई नमूनों से आश्चर्यचकित हूं कि अत्यधिक पूंछ में है। मुझे आश्चर्य है कि ऐसा क्यों है कि वे बहुत अधिक महंगे हैं। JIT 1 या 2 हो सकता है लेकिन 20 नहीं। शर्त? बीच में आता है? अन्य? अपडेट के लिए फिर से धन्यवाद।
EngrStudent

आपका स्वागत है, विचारों के लिए धन्यवाद। पता नहीं, मैंने वास्तव में इसे "स्वतंत्र रूप से" चलाने की अनुमति दी थी।
डीजेवी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.