2016-11-11 6 views
0

ので、私はそれらの両方が同一の構造を有し、2つのデータフレームを有する:加算値 - 実行時間

V1 V2 V3 V4 C 
0 1 1 0 -1 
0 0 1 0 -1 
2 0 0 0 1 
2 0 0 0 1 
1 0 0 0 1 
2 0 0 0 1 

V1-V4列が整数型で、C列が持つ係数であります2レベル。 データフレームのサイズは異なります。最初のフレームは50,000行、もう1つは600,000行あります。私は「system.time」と、データがそれをフレーム50000行に対して、この関数の実行時間をテストした

SimpleFunction <- function(dataset) { 
    progress.bar <- create_progress_bar("text") 
    progress.bar$init(nrow(dataset)) 
    for (i in 1:nrow(dataset)) { 
    row.sum <- sum(dataset[i,1:4]) 
    dataset[i,1] <- dataset[i,1]/row.sum 
    dataset[i,2] <- dataset[i,2]/row.sum 
    dataset[i,3] <- dataset[i,3]/row.sum 
    dataset[i,4] <- dataset[i,4]/row.sum 
    progress.bar$step() 
    } 
    return(dataset) 
} 

:私は、この行の要素の合計によって列の各要素を分ける簡単な関数を書きました〜45秒でしたが、600000行のデータフレームでは非常に時間がかかっていました(1%で約2分、 "plyr"パッケージのこの単純なプログレスバーで測定します)。今私の質問は:なぜですか?変更されたのは行の数だけで、データフレームの構造は同じです。 50000 - 45秒、600000 - 540秒のような線形成長ではないでしょうか? 私は単純に大きなデータフレームを分割し、各フラグメントで関数を実行してから再び結合することができますが、なぜこれが起こっているのか分かりません。

答えて

1

このループにはループを使用する必要はありません。ベクトル化された計算に特化しています。ループスルー行はすべて処理時間が長くなります。そのように、あなたはこれを行うことができますし、Rは、行ごとに行の合計を作成します。

row.sum <- rowSums(dataset[,1:4]) 
dataset[,1] <- dataset[,1]/row.sum 
dataset[,2] <- dataset[,2]/row.sum 
dataset[,3] <- dataset[,3]/row.sum 
dataset[,4] <- dataset[,4]/row.sum 
+0

row.sum < - sum(dataset [、1:4])は、各行から要素の合計のベクトルを返しません - 列1:4のすべての要素(スカラー)の合計を返します。 –

+0

はい、申し訳ありません。あなたは 'rowSums(dataset [、1:4])'を使う必要があります。あなたは間違いなくループを使う必要はありません。 – MorganBall

+0

それはrow.sum < - rowSums(dataset [、1:4])thoで動作し、私の問題を解決します - ありがとうございます。 –

1

sweepあなたは1行のソリューションをしたい場合は、ここに便利です:

> dataset[, 1:4] <- sweep(dataset[,-5], 1, rowSums(dataset[,-5]), FUN="/") 
> dataset 
    V1 V2 V3 V4 C 
1 0 0.5 0.5 0 -1 
2 0 0.0 1.0 0 -1 
3 1 0.0 0.0 0 1 
4 1 0.0 0.0 0 1 
5 1 0.0 0.0 0 1 
6 1 0.0 0.0 0 1 

applyも適しています。

dataset[, -5] <- apply(dataset[,-5], 2, function(x) x/rowSums(dataset[,-5]))