web-dev-qa-db-ja.com

ベクトルに少なくとも1つのNAがあるかどうかを検出する最も速い方法は?

Rにベクトルに少なくとも1つのNAがあるかどうかを検出する最も速い方法は何ですか?私は使用しています:

sum( is.na( data ) ) > 0

ただし、各要素、強制、および合計関数を調べる必要があります。

65
SFun28

R 3.1.0以降、anyNA()がこれを行う方法です。原子ベクターでは、any(is.na())の場合のようにベクター全体を通過する代わりに、最初のNAの後に停止します。また、これにより、すぐに破棄されるis.naを使用した中間論理ベクトルの作成が回避されます。ヨランの例を借りる:

x <- y <- runif(1e7)
x[1e4] <- NA
y[1e7] <- NA
microbenchmark::microbenchmark(any(is.na(x)), anyNA(x), any(is.na(y)), anyNA(y), times=10)
# Unit: microseconds
#           expr        min         lq        mean      median         uq
#  any(is.na(x))  13444.674  13509.454  21191.9025  13639.3065  13917.592
#       anyNA(x)      6.840     13.187     13.5283     14.1705     14.774
#  any(is.na(y)) 165030.942 168258.159 178954.6499 169966.1440 197591.168
#       anyNA(y)   7193.784   7285.107   7694.1785   7497.9265   7865.064

ベクトルの最後の値を変更しても、大幅に高速化されることに注意してください。これは、一部には、中間論理ベクトルが回避されるためです。

54
BrodieG

考えている:

any(is.na(data))

少し速くなるはずです。

68
Sacha Epskamp

これを Rcpp プレゼンテーションの一部で言及し、実際にはRソリューションを介したRcppを使用した埋め込みC++からかなり大きなゲインを示すベンチマークがあります。

  • ベクトル化されたRソリューションは、まだベクトル式のすべての単一要素を計算します

  • 目標がany()を満たすだけの場合、最初のマッチ後に中止できます-これはRcpp sugar(本質的に:C++式を作成するためのC++テンプレートマジックです) R式のように見えます。詳細については、 this vignette を参照してください。

そのため、コンパイルされた特殊なソリューションを機能させることにより、実際に高速なソリューションを実現できます。これをこのSOの質問で提供されているソリューションと比較していないが、パフォーマンスについてはかなり自信がある。

編集 Rcppパッケージには、sugarPerformanceディレクトリにサンプルが含まれています。 any()の 'R-computes-full-vector-expression'よりも数千の 'sugar-can-abort-soon'の増加がありますが、その場合は、 is.na()が、単純なブール式。

16

NAで停止するforループを記述できますが、system.timeはNAの場所に依存します...(存在しない場合はlooooongかかります)

set.seed(1234)
x <- sample(c(1:5, NA), 100000000, replace = TRUE)

nacount <- function(x){
  for(i in 1:length(x)){
    if(is.na(x[i])) {
      print(TRUE)
      break}
}}

system.time(
  nacount(x)
)
[1] TRUE
       User      System verstrichen 
       0.14        0.04        0.18 

system.time(
  any(is.na(x))
) 
       User      System verstrichen 
       0.28        0.08        0.37 

system.time(
  sum(is.na(x)) > 0
)
       User      System verstrichen 
       0.45        0.07        0.53 
8
EDi

これまでに説明したさまざまな方法のいくつかについて、私の(低速の)マシンからの実際の時間を次に示します。

x <- runif(1e7)
x[1e4] <- NA

system.time(sum(is.na(x)) > 0)
> system.time(sum(is.na(x)) > 0)
   user  system elapsed 
  0.065   0.001   0.065 

system.time(any(is.na(x)))  
> system.time(any(is.na(x)))
   user  system elapsed 
  0.035   0.000   0.034

system.time(match(NA,x)) 
> system.time(match(NA,x))
  user  system elapsed 
 1.824   0.112   1.918

system.time(NA %in% x) 
> system.time(NA %in% x)
  user  system elapsed 
 1.828   0.115   1.925 

system.time(which(is.na(x) == TRUE))
> system.time(which(is.na(x) == TRUE))
  user  system elapsed 
 0.099   0.029   0.127

match%in%は同様です。なぜなら%in%matchを使用して実装されます。

6
joran

あなたが試すことができます:

d <- c(1,2,3,NA,5,3)

which(is.na(d) == TRUE, arr.ind=TRUE)
3
Manuel Ramón