NA
ベクトルがRに少なくとも1つあるかどうかを検出する最速の方法は何ですか? 私は使用しています:
sum( is.na( data ) ) > 0
しかし、それには、各要素、型変換、および sum 関数を調べる必要があります。
考えている:
any(is.na(data))
少し速くなるはずです。
R 3.1.0 以降anyNA()
は、これを行う方法です。原子ベクトルでは、これは の場合のようにベクトル全体を通過するのではなく、最初の NA の後に停止しany(is.na())
ます。is.na
さらに、これにより、すぐに破棄される中間論理ベクトルの作成が回避されます。Joranの例を借りる:
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
ベクトルの最後の値を変更しても、大幅に高速化されていることに注意してください。これは、中間の論理ベクトルを回避するためです。
これについては、いくつかのRcppプレゼンテーションで言及しており、実際にはいくつかのベンチマークがあり、R ソリューションよりも Rcpp を使用した組み込み C++の方がかなり大きな利点があることを示しています。
ベクトル化された R ソリューションは、ベクトル式のすべての要素を計算します。
あなたの目標が を満たすことだけならany()
、最初の一致の後に中止することができます -- これが、私たちのRcpp シュガー(本質的には、C++ 式を R 式のように見せるための C++ テンプレート マジックです。詳細については、このビネットを参照してください) ソリューションが行うことです。 .
したがって、コンパイルされた特殊なソリューションを機能させることで、実際に高速なソリューションを得ることができます。これをこのSOの質問で提供されているソリューションと比較していませんが、パフォーマンスについてはかなり自信があります.
編集Rcpp パッケージにはディレクトリに例が含まれていますsugarPerformance
。の「R-computes-full-vector-expression」よりも「sugar-can-abort-soon」が数千増加していますが、そのケースには単純なブール式がany()
含まれていないことを付け加えておきます。is.na()
NAで停止するforループを作成することもできますが、system.timeは、NAがどこにあるかによって異なります...(存在しない場合は、非常に時間がかかります)
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
これまでに説明したさまざまな方法のいくつかについて、私の(遅い)マシンからの実際の時間は次のとおりです。
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
あなたが試すことができます:
d <- c(1,2,3,NA,5,3)
which(is.na(d) == TRUE, arr.ind=TRUE)