2017-12-12 11 views
2

私はいくつかの統計を行うために、dataframe1とdataframe2の各行を比較します。これらは大規模なデータフレーム(300,000行と40,000行)なので、比較するのは大変です。R分割DFと並行してテストを実行

私はいくつかの機能を使って統計を適用しました。私が疑問に思っていたことは、dataframe1をチャンクに分割することが可能かどうかということでした。これらのチャンクは複数のコアで並列に実行されます。

library(lawstat) 
library(reshape2) 
df1 = matrix(ncol= 100, nrow=100) 
for (i in 1:100){ 
    df1[,i] =floor(runif(100, min = 0, max =3)) 
} 

df2 = matrix(ncol= 100, nrow=1000) 
for (i in 1:100){ 
    df2[,i] =runif(1000, min = 0, max =1000) 
} 

testFunc<- function(df1, df2){ 
     x=apply(df1, 1, function(x) apply(df2, 1, function(y) levene.test(y,x)$p.value)) 
     x=melt(x) 
     return(x) 
    } 

system.time(res <- testFunc(df1,df2)) 

統計(例えばレーベンテスト)ので、私は素晴らしいことだこれをスピードアップすることができます任意の方法を計算するためにかなり長い時間がかかるの一部

+1

私は特定のソリューションを書くかテストする時間がありませんが、これは確かに 'parallel'パッケージを使って達成できます。 'ライブラリ(パラレル); ?parRapply' – bdemarest

+0

データフレームをマトリックスに強制できますか? (数値データは入っていますか?) –

+0

はい数値データであり、マトリックスに入れることができます – George

答えて

2

あり、最適化の余地があなたの関数であるが、ここparallelパッケージを使用して改善の一例である:私のマシン上で

library(parallel) 
library(snow) 

# I have a quad core processor so I am using 3 cores here. 
cl <- snow::makeCluster(3) 
testFunc2<- function(df1, df2){ 
    x=parallel::parApply(cl = cl, X = df1, 1, function(x, df2) apply(df2, 1, 
function(y) lawstat::levene.test(y,x)$p.value), df2) 
    x=melt(x) 
    return(x) 
} 
system.time(res <- testFunc2(df1,df2)) 

私は3のクラスタサイズを持っている場合、これは、少なくとも実行している時間を半減

編集:あなたのコードを解読していないと悪いと感じたので、以下のように、levene.test関数を削除して、ほとんどの家庭/職場で並行してパフォーマンスを向上させます。

lev_lite = function(y, group){ 
    N = 100 # or length(y) 
    k = 3 # or length(levels(group)) after setting to as.factor below 

    reorder <- order(group) 
    group <- group[reorder] 
    y <- y[reorder] 
    group <- as.factor(group) 
    n <- tapply(y,group, FUN = length) 
    yi_bar <- tapply(y,group, FUN = median) 
    zij = abs(y - rep(yi_bar, n)) 
    zidot = tapply(zij, group, FUN = mean) 
    zdotdot = mean(zij) 
    # test stat, see wiki 
    W = ((N - k)/(k - 1)) * (
    sum(n*(zidot - zdotdot)^2)/ 
     sum((zij - rep(zidot, n))^2)) 

    #p val returned 
    1 - pf(W, k-1, N-k) 
} 

testFunc2<- function(df1, df2){ 
    x=apply(df1, 1, function(x) apply(df2, 1, lev_lite, group = x)) 
    x=melt(x) 
    return(x) 
} 

> system.time(res <- testFunc(df1[1:50, ],df2[1:50,])) 
user system elapsed 
5.53 0.00 5.56 
> system.time(res2 <- testFunc2(df1[1:50, ],df2[1:50, ])) 
user system elapsed 
1.13 0.00 1.14 
> max(res2 - res) 
[1] 2.220446e-15 

これはパラレル化なしで約5倍の改善です。

+0

華麗な、最適化の考え方は何ですか? あなたの答えは、私が後にしたものです! – George

+1

私はあなたがこの分析を定期的に実行するかどうかにかかっていると思いますが、シミュレーションを実行している場合や非常にきれいなデータセットを使用している場合は、ビルドインされた関数のバージョンを削除することができます。私は例を含めるために私のコメントを編集しています。私はソース/ウィキペディアを使って 'lev_lite'を書きました(私の編集を見てください)。 – bmrn

+0

ああ、そうです。私が正確なテストを知ったら、私は実行します。あなたが上で行ったように、ライト版を実装します。 – George

関連する問題