dplyr (केस-वार विलोपन) का उपयोग करके data.frame में पूर्ण मामलों के लिए फ़िल्टर


98

क्या dplyr का उपयोग करके पूर्ण मामलों के लिए data.frame को फ़िल्टर करना संभव है? complete.casesसभी चर कार्यों की एक सूची के साथ, निश्चित रूप से। लेकिन यह एक) क्रिया है जब बहुत सारे चर होते हैं और बी) असंभव होते हैं जब चर नाम ज्ञात नहीं होते हैं (उदाहरण के लिए एक फ़ंक्शन में जो किसी भी डेटा.फ्रेम को संसाधित करता है)।

library(dplyr)
df = data.frame(
    x1 = c(1,2,3,NA),
    x2 = c(1,2,NA,5)
)

df %.%
  filter(complete.cases(x1,x2))

4
complete.casesसिर्फ वैक्टर स्वीकार नहीं करता है। यह पूरे डेटा फ्रेम, साथ ही लेता है।
जोरन

लेकिन यह dplyrफ़िल्टर फ़ंक्शन के भाग के रूप में काम नहीं करता है । मुझे लगता है कि मैं पर्याप्त स्पष्ट नहीं था और अपने प्रश्न को अपडेट किया।
user2503795

1
यह मदद करता है कि अगर आप वास्तव में प्रदर्शित कर सकते हैं कि यह कैसे काम नहीं करता है, लेकिन जब मैं इसे फ़िल्टर के साथ आज़माता हूं, तो यह ठीक काम करता है।
जोरन

जवाबों:


186

इसे इस्तेमाल करे:

df %>% na.omit

या यह:

df %>% filter(complete.cases(.))

या यह:

library(tidyr)
df %>% drop_na

यदि आप एक चर के लापता होने के आधार पर फ़िल्टर करना चाहते हैं, तो एक सशर्त का उपयोग करें:

df %>% filter(!is.na(x1))

या

df %>% drop_na(x1)

अन्य उत्तर इंगित करते हैं कि ऊपर दिए गए समाधान na.omitबहुत धीमे हैं लेकिन इस तथ्य के खिलाफ संतुलित होना होगा कि यह na.actionविशेषता में छोड़ी गई पंक्तियों के पंक्ति सूचकांकों को लौटाता है जबकि ऊपर दिए गए अन्य समाधान नहीं करते हैं।

str(df %>% na.omit)
## 'data.frame':   2 obs. of  2 variables:
##  $ x1: num  1 2
##  $ x2: num  1 2
##  - attr(*, "na.action")= 'omit' Named int  3 4
##    ..- attr(*, "names")= chr  "3" "4"

ADDED ने dplyr और टिप्पणियों के नवीनतम संस्करण को प्रतिबिंबित करने के लिए अपडेट किया है।

ADDED ने tidyr और टिप्पणियों के नवीनतम संस्करण को प्रतिबिंबित करने के लिए अद्यतन किया है।


बस जवाब देने के लिए वापस आया और आपका उपयोगी उत्तर देखा!
infominer

1
धन्यवाद! मैंने कुछ बेंचमार्क परिणाम जोड़े। na.omit()बहुत खराब प्रदर्शन करता है, लेकिन एक तेज है।
user2503795

1
अब यह रूप में अच्छी तरह से काम करता है: df %>% filter(complete.cases(.))। सुनिश्चित नहीं है कि हाल ही में dplyr में बदलावों ने इसे संभव बनाया है।
user2503795

जैसा कि @ जान-कटिंस बताते हैं, Tidyverse फ़ंक्शन को कहा जाता है drop_na, इसलिए आप अब कर सकते हैं df %>% drop_na():।
मलबे

26

यह मेरे लिए काम करता है:

df %>%
  filter(complete.cases(df))    

या थोड़ा और सामान्य:

library(dplyr) # 0.4
df %>% filter(complete.cases(.))

इससे यह लाभ होगा कि डेटा को फ़िल्टर में पास करने से पहले श्रृंखला में संशोधित किया जा सकता था।

अधिक कॉलम के साथ एक और बेंचमार्क:

set.seed(123)
x <- sample(1e5,1e5*26, replace = TRUE)
x[sample(seq_along(x), 1e3)] <- NA
df <- as.data.frame(matrix(x, ncol = 26))
library(microbenchmark)
microbenchmark(
  na.omit = {df %>% na.omit},
  filter.anonymous = {df %>% (function(x) filter(x, complete.cases(x)))},
  rowSums = {df %>% filter(rowSums(is.na(.)) == 0L)},
  filter = {df %>% filter(complete.cases(.))},
  times = 20L,
  unit = "relative")

#Unit: relative
#             expr       min        lq    median         uq       max neval
 #         na.omit 12.252048 11.248707 11.327005 11.0623422 12.823233    20
 #filter.anonymous  1.149305  1.022891  1.013779  0.9948659  4.668691    20
 #         rowSums  2.281002  2.377807  2.420615  2.3467519  5.223077    20
 #          filter  1.000000  1.000000  1.000000  1.0000000  1.000000    20

1
मैंने आपके उत्तर को "" के साथ अपडेट किया। में पूर्ण। मामलों और जोड़ा बेंचमार्क - आशा है कि आप बुरा मत मानना ​​:-)
तालक

:) मैं नही। धन्यवाद।
मिहा ट्रॉश

1
मैंने पाया df %>% slice(which(complete.cases(.)))कि ऊपर दिए गए बेंचमार्क में फ़िल्टर-एप्रोच की तुलना में ~ 20% तेज प्रदर्शन किया।
तात

यह ध्यान देने योग्य है कि यदि आप अन्य dplyr कमांड (जैसे group_by ()) के साथ dplyr पाइप में इस फ़िल्टर का उपयोग कर रहे हैं, तो %>% data.frame() %>%आपको कोशिश करने से पहले जोड़ना होगा और पूर्ण. cases (।) पर फ़िल्टर करना होगा क्योंकि यह काम नहीं करेगा। tibbles या समूहीकृत tibbles या कुछ और। या कम से कम, जो अनुभव मुझे हुआ है।
सी। डेनी

16

ग्रोथेंडिक के उत्तर के लिए कुछ बेंचमार्क परिणाम यहां दिए गए हैं। na.omit () अन्य दो समाधानों के रूप में 20x अधिक समय लेता है। मुझे लगता है कि अगर फिल्टर के हिस्से के रूप में इसके लिए एक फ़ंक्शन होता है, तो यह अच्छा होगा।

library('rbenchmark')
library('dplyr')

n = 5e6
n.na = 100000
df = data.frame(
    x1 = sample(1:10, n, replace=TRUE),
    x2 = sample(1:10, n, replace=TRUE)
)
df$x1[sample(1:n, n.na)] = NA
df$x2[sample(1:n, n.na)] = NA


benchmark(
    df %>% filter(complete.cases(x1,x2)),
    df %>% na.omit(),
    df %>% (function(x) filter(x, complete.cases(x)))()
    , replications=50)

#                                                  test replications elapsed relative
# 3 df %.% (function(x) filter(x, complete.cases(x)))()           50   5.422    1.000
# 1               df %.% filter(complete.cases(x1, x2))           50   6.262    1.155
# 2                                    df %.% na.omit()           50 109.618   20.217

12

यह एक छोटा फ़ंक्शन है जो आपको कॉलम निर्दिष्ट करता है (मूल रूप से वह सब कुछ जो dplyr::selectसमझ सकता है) जिसमें कोई NA मान नहीं होना चाहिए (पांडा df.dropna () के बाद मॉडलिंग ):

drop_na <- function(data, ...){
    if (missing(...)){
        f = complete.cases(data)
    } else {
        f <- complete.cases(select_(data, .dots = lazyeval::lazy_dots(...)))
    }
    filter(data, f)
}

[ drop_na अब tidyr का हिस्सा है : ऊपर इसके द्वारा प्रतिस्थापित किया जा सकता है library("tidyr")]

उदाहरण:

library("dplyr")
df <- data.frame(a=c(1,2,3,4,NA), b=c(NA,1,2,3,4), ac=c(1,2,NA,3,4))
df %>% drop_na(a,b)
df %>% drop_na(starts_with("a"))
df %>% drop_na() # drops all rows with NAs

0.5 की तरह कटऑफ जोड़ने में सक्षम होने के लिए और भी उपयोगी नहीं होगा और क्या यह कॉलम द्वारा प्रक्रिया है? मामला: 50% से अधिक और गायब डेटा के साथ चर को समाप्त करें। उदाहरण: डेटा [-which (colMeans (is.na (data))> 0.5)] यह अच्छा होगा कि यह tidyr के साथ किया जा सके।
17

@ मोंडुइज़ का मतलब यह होगा कि अधिक डेटा (जहां एक वैरिएबल है, जिसमें बहुत सारे NA हैं) का जोड़ पाइपलाइन में अगला चरण विफल हो सकता है क्योंकि एक आवश्यक चर अब गायब है ...
Jan Katins

सही है, यह समझ में आता है।
मोंडुइज़

6

इसे इस्तेमाल करे

df[complete.cases(df),] #output to console

या यह भी

df.complete <- df[complete.cases(df),] #assign to a new data.frame

उपरोक्त कमांड आपके डेटा.फ्रेम में सभी स्तंभों (चर) के लिए पूर्णता की जांच करने का ध्यान रखते हैं।


धन्यवाद। मुझे लगता है कि मैं पर्याप्त स्पष्ट नहीं था (प्रश्न अद्यतन)। मैं कम्प्लीट.केस (df) के बारे में जानता हूं लेकिन मैं इसे dplyrफिल्टर फंक्शन के हिस्से के रूप में करना चाहता हूं । कि dplyr जंजीरों आदि में एक साफ एकीकरण की अनुमति होगी
user2503795

20G पर @ G.Grothendieck
infominer

में dplyr:::do.data.frameबयान env$. <- .dataपर्यावरण के लिए डॉट कहते हैं। Magrittr में ऐसा कोई वक्तव्य नहीं :: "%>%" `
G. Grothendieck

क्षमा करें, गलत जगह टिप्पणी दर्ज की गई है।
जी। ग्रोथेंडिक

3

पूर्णता के लिए, dplyr::filterपूरी तरह से बचा जा सकता है , लेकिन अभी भी सिर्फ magrittr:extract(एक [) का उपयोग करके श्रृंखलाओं को बनाने में सक्षम हैं :

library(magrittr)
df = data.frame(
  x1 = c(1,2,3,NA),
  x2 = c(1,2,NA,5))

df %>%
  extract(complete.cases(.), )

अतिरिक्त बोनस गति है, यह filterऔर na.omitवेरिएंट के बीच सबसे तेज़ तरीका है (@Miha Trošt microbenchmarks का उपयोग करके परीक्षण किया गया)।


जब मैं Miha Trošt द्वारा डेटा के साथ बेंचमार्क करता हूं, तो मुझे लगता है कि उपयोग करने extract()की तुलना में लगभग दस गुना धीमा है filter()। हालाँकि, जब मैं एक छोटा डेटा फ्रेम बनाता हूं df <- df[1:100, 1:10], तो चित्र बदल extract()जाता है और सबसे तेज़ होता है।
स्टिबू

तुम सही हो। ऐसा लगता magrittr::extractहै कि n <= 5e3मिहा ट्रॉस्च बेंचमार्क में केवल तभी सबसे तेज़ तरीका है ।
mbask 24:17
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.