2014-03-12 55 views
44

是否可以使用dplyr過濾完整個案的data.frame?當然,complete.cases列出了所有變量的作品。但是,a)當有很多變量時是冗長的,b)當變量名稱未知時(例如,在處理任何數據幀的函數中),不可能。使用dplyr(個案刪除)過濾data.frame中的完整個案

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

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

'complete.cases'不只是接受向量。它也需要整個數據幀。 – joran

+0

但是,這並不是'dplyr'的過濾功能的一部分。我想我還不夠清楚,並更新了我的問題。 – user2503795

+1

這將有助於如果你能證明它如何不能與dplyr一起工作,但是當我用過濾器嘗試它時,它工作得很好。 – joran

回答

92

試試這個:

df %>% na.omit 

或本:

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

ADDED已經更新,以反映最新版本dplyr和評論。

+0

剛回來回答,看到了你有用的答案! – infominer

+1

謝謝!我添加了一些基準結果。 'na.omit()'表現很差,但速度很快。 – user2503795

+1

現在也適用:'df%>%filter(complete.cases(。))'。不確定最近dplyr的變化是否可能。 – user2503795

6

試試這個

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

甚至這個

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

上述命令採取的完整性檢查所有列(變量) 在data.frame照顧。

+0

謝謝。我想我還不夠清楚(問題更新)。我知道complete.cases(df),但我想用'dplyr'作爲過濾函數的一部分。這將允許在dplyr鏈等整合。 – user2503795

+0

檢查答案由@ G.Grothendieck – infominer

+0

在'dplyr ::: do.data.frame'語句'env $。 < - .data'爲環境添加點。 magrittr ::「%>%」中沒有這樣的聲明' –

7

以下是格洛騰迪克回覆的一些基準測試結果。 na.omit()比其他兩種解決方案花費的時間要多20倍。我認爲如果dplyr有一個函數可以作爲過濾器的一部分,那將會很好。

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 
+0

這個答案值得這麼多票!... –

20

這個工作對我來說:

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 
+0

我更新你的答案與「。」在complete.cases和增加的基準 - 希望你不介意:-) –

+0

:)我不知道。謝謝。 –

+1

我發現'df%>%slice(complete.cases(。)))'比上述基準中的過濾器方法執行速度快了20%。 –

8

這是一個簡短的功能,它可以讓你指定的列(基本上是所有這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 is now part of 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

如果能夠添加像0.5這樣的臨界值並且讓它按列進行處理,那將會更有用嗎?案例:消除50%以上缺失數據的變量。例如:data [,-which(colMeans(is.na(data))> 0.5)]能夠用tidyr做到這一點是很好的。 – Monduiz

+0

@Monduiz這意味着添加更多的數據(其中一個變量有很多NA)可能會導致流水線中的下一個步驟失敗,因爲現在缺少所需的變量... –

+0

對,這很有道理。 – Monduiz

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(.),) 

附加獎金是速度,這是filterna.omit變種(使用@MihaTroštmicrobenchmarks進行測試)中最快的方法。

+0

當我用MihaTrošt的數據做基準時,我發現使用'extract()'幾乎比filter()慢10倍。然而,當我用'df < - df [1:100,1:10]'創建一個更小的數據框時,圖片變化和'extract()'是最快的。 – Stibu

+0

你是對的。它看起來像'magrittr :: extract'是MihaTrošt基準測試中'n <= 5e3'時最快的方法。 – mbask