Dplyrを使用して完全なケースのdata.frameをフィルタリングすることは可能ですか? complete.cases
もちろん、すべての変数のリストが機能します。しかし、それは、a)多くの変数がある場合は冗長であり、b)変数名がわからない場合は不可能です(たとえば、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))
これを試して:
df %>% na.omit
またはこれ:
df %>% filter(complete.cases(.))
またはこれ:
library(tidyr)
df %>% drop_na
1つの変数の欠落に基づいてフィルタリングする場合は、条件を使用します。
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とコメントの最新バージョンを反映するように更新しました。
これは私のために働く:
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
Grothendieckの回答のベンチマーク結果を次に示します。 na.omit()は、他の2つのソリューションの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
これを試して
df[complete.cases(df),] #output to console
またはこれでさえ
df.complete <- df[complete.cases(df),] #assign to a new data.frame
上記のコマンドは、data.frameのすべての列(変数)の完全性をチェックします。
完全を期すために、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
バリアント(@MihaTroštマイクロベンチマークを使用してテスト済み)の中で最速の方法です。