2016-10-25 14 views
0

非常に単純なコードをRで書いていますが、データ> 2.000.000行に使用するとほぼ2時間かかります。else loop in R

コードを改善する機会はありますか?私は可能な限り簡単な解決策を望んでいます。

私のRスキルは大丈夫です(経験< 1年)が、この場合は限界に達しました。 Furthemore他のループの場合、スピードアップに関するいくつかの記事を読んだが、どの戦略が自分のコードに最も適しているかわからない(例:Vectorise、ifelse、Parallelismなど)

ありがとう。

system.time(
     for (i in 1:(length(mydata$session_id)-1)){ 
     if (mydata$session_id[i] != mydata$session_id[i+1]){ 
      mydata$Einstiegskanal[i]="1" 
     } else { 
      mydata$Einstiegskanal[i]="0" 
     } 
     } 
    ) 

    # 6877,1 Seconds = 1,91 h 
+1

'ライブラリ(dplyr); MYDATA%>%に変異(Einstiegskanal = ifelse(SESSION_ID =ラグ(SESSION_ID)、 "1"、 "0")!)' – ExperimenteR

答えて

3

あなたがやっていることは、ある行から次の行へのIDの違いにすぎません。これに対してdiffが作成されました。

session_id <- sample(1:10, size = 2000000, replace = TRUE) 

system.time({ 
    ifelse(c(diff(session_id) == 0, NA), "1", "0") 
}) 
    user system elapsed 
    0.64 0.05 0.69 

本当にスピードアップしたい場合は、ifelseも避けてください。

あなたのコードは2つのアプローチの間の速度の比較のために

lgl <- c(diff(x) == 0, NA) 

mydata$Einstiegskanal[!lgl] <- "1" 
mydata$Einstiegskanal[lgl] <- "0" 

次のようになります。

library(microbenchmark) 
session_id <- sample(1:10, size = 2000000, replace = TRUE) 

y <- vector("character", length(session_id)) 

microbenchmark(
    with_ifelse = ifelse(c(diff(session_id) == 0, NA), "1", "0"), 
    avoid_ifelse = { 
    lgl <- c(diff(session_id) == 0, NA) 
    y[lgl] <- "1" 
    y[!lgl] <- "0" 
    }, 
    times = 10) 

Unit: milliseconds 
     expr  min  lq  mean median  uq  max neval cld 
    with_ifelse 684.69879 686.16912 710.3928 714.88029 726.61384 736.1481 10 b 
avoid_ifelse 88.75335 89.21844 98.8694 90.46677 92.03064 139.8182 10 a 
+0

非常に素晴らしいです!私はシフト機能を使って比較することを考えていましたが、これは本当にエレガントです! – User2321

0

あなたはそのようcomething試すことができます。

mydata <- data.frame(session_id = round(runif(2e6, 0, 10), 0)) 
mydata2 <- data.frame(session_id = mydata[-1,]) 
mydata$Einstiegskanal <- c(ifelse(mydata$session_id[1:(nrow(mydata)-1)]==mydata2,1,0), NA) 

このベクトルはdfより1つの少ない要素を持っていると私はNAdf$Equalの最後の値を設定します。

0

は、あなたの答えをありがとうございました!

ベンジャミンの次の適合コードは私にとっては完璧に機能します:) elseと組み合わせたdiff関数は非常にスマートで、私のelse ifループの多くで動作します。

system.time({ 
    mydata$Einstiegskanal<-ifelse(c(diff(mydata$session_id) == 0, NA), "0", "1") 
})