2017-07-05 13 views
1

forループとapply関数の間に大きな時間差があります。Apply関数がForループよりも100時間長くなります。

は私が各列のNAの割合が何であるかをチェックし、私は検査するための新たなDFとして結果を返すようにしたい73個の列で約20万レコードを含むデータフレーム(alldat)を持っています。 apply関数は4秒とするために取る

datacheck <- as.data.frame(apply(alldat,2,function (x) round(sum(is.na(x))/dim(alldat)[1], digits = 2))) 

1)機能forループを有する:カラムによって

Nacheck = function(a){ 
    a <- as.data.frame(a) 
    vecNA <- rep(NA, dim(a)[2]) 
    for (i in 1:dim(a)[2]){ 
     vecNA[i] <- sum(is.na(a[, i])) 
     } 
    rowss <- rep(nrow(a), length(vecNA)) 
    NA_PCT <- vecNA/rowss 
    colna <- colnames(a) 
    datacheck <- as.data.frame(t(rbind(colna, NA_PCT))) 
    return(datacheck) 
} 
datacheck1 = Nacheck(alldat) 

2)apply関数I 2つの方法でそれを行っていますループ機能が0.023秒未満である。

start.time <- Sys.time() 
datacheck <- as.data.frame(apply(alldat,2,function (x) round(sum(is.na(x))/dim(alldat)[1], digits = 2))) 
end.time <- Sys.time() 
time.takenapply <- end.time - start.time 
time.takenapply 

時間4.304秒

forループ時間の違い:

start.time <- Sys.time() 
datacheck = Nacheck(alldat) 
end.time <- Sys.time() 
time.taken <- end.time - start.time 
time.taken 

は0.02399993秒

の時間差、私は何か間違ったことをやっていますか?この時差の原因は何ですか?

+0

'apply'関数は行列を引数として取ります。入力データを行列に内部変換すると、この時間差が生じることがあります。また、列の上で計算を実行するので、代わりに 'lapply'を使用します。 –

+0

または 'apply(df、2、function(x)sum(is.na(x)))' – amonk

+0

これは原因ではありませんが、なぜ 'nrow(a)'、 'ncol(a)' 'dim(a)[1]'、 'dim(a)[2]'の代わりに? – digEmAll

答えて

1

日付フレームはリストと内部で非常に似ており、各列はリスト内の別個のエントリです。これは、$演算子を使用して確認できます。これにより、リストに名前付きエントリを指定するのと同様に、列を指定することができます。

applyを実行すると、Natrave Drovaは既にコメントに記載されているように、あなたはentiryデータフレームを暗黙的にマトリックスに変換しています。データフレームに数字や文字列の列などの異なるデータ型がある場合は、すべての値が共通の型(通常は文字)に変換されます。あなたのデータフレームが大きければ(そして、200k * 73の値を強制的に大きくすると)、これは非常にコストのかかる操作になります。

したがって、*apply関数をforループと適切に比較する場合は、代わりにlapplyを試してみる必要があります。

関連する問題