2016-07-22 3 views
2

に設定高速data.tableとループと私は、データテーブルを持っていると私は日が列名と一致する各行の1を割り当て、各ユニークな毎日のために新しい列を作成し、したいR

私はこれをforループを使って行っていますが、data.tableを使って最適化する方法があるのか​​どうか、疑問に思っていました。ここで

は一例であり

dt <- data.table(Week_Day = c("Monday", "Tuesday", "Wednesday", 
          "Thursday", "Friday", "Saturday", "Sunday")) 

Day <- unique(dt$Week_Day) 
for (i in 1:length(Day)) { 
    if (Day[i] != "Sunday") { 
     dt[, Day[i] := ifelse(Week_Day == Day[i], 1, 0)] 
    } 
} 

私のテーブルには、298Kの行であり、それは(下)実行に時間はかかりませんが、長いスクリプトのその部分と、私はかなりの数の非効率的なループを持っているので、I全体の実行時間をダウンさせようとしています。事前に

user system elapsed 
0.99 0.06 1.05 

感謝を:実行するための

時間。これは、バイナリ二の鎖に検索し、参照することにより、交換してifelseの排除を含むdata.tableスピードアップのカップルを実装し

Day <- unique(dt$Week_Day) 
setkey(dt, Week_Day) 

# create columns of 0s 
dt[, (Day) := 0L] 

for (i in seq_along(head(Day, -1))) { 
    dt[Day[i], Day[i] := 1L] 
} 

+0

は 'model.matrix()'にも見てください。おそらく、あなたはそのようなものを使いたいかもしれません。 – abhiieor

+1

関連する質問:@arun、ありがとう、@stackoverflow.com/q/18881073/ – Frank

答えて

4

ここで、パフォーマンスが向上異なるアプローチがあります質問

1)における独創的なアプローチよりも0で新しい列を初期化日曜日

​​

2)以外のユニークな日を取得します。

dt[, (Day) := 0L] 

3)ループが参照により1Sと更新:

for(x in Day) { 
    set(dt, i = which(dt[["Week_Day"]] == x), j = x, value = 1L) 
} 

シンプルな性能比較:

dt1 <- data.table(Week_Day = sample(c("Monday", "Tuesday", "Wednesday", 
           "Thursday", "Friday", "Saturday", "Sunday"), 3e5, TRUE)) 

dt2 <- copy(dt1) 


system.time({ 
    Day <- setdiff(unique(dt$Week_Day), "Sunday") 
    dt1[, (Day) := 0L] 
    for(x in Day) { 
    set(dt1, i = which(dt1[["Week_Day"]] == x), j = x, value = 1L) 
    } 
}) 
#  User  System verstrichen 
#  0.029  0.003  0.032 

system.time({ 
    Day <- unique(dt$Week_Day) 
    for (i in 1:length(Day)) { 
    if (Day[i] != "Sunday") { 
     dt2[, Day[i] := ifelse(Week_Day == Day[i], 1L, 0L)] 
    } 
    } 
}) 

#  User  System verstrichen 
#  0.138  0.070  0.210 


all.equal(dt1, dt2) 
#[1] TRUE 
+0

素晴らしい!私の300k行のデータでは実行時間は 'user system elapsed' ' 0.02 0.00 0.01' となりました。これは、「あまりにも長い」入れ子になっているループに関する別の質問を投稿してしまいます。 – MidnightDataGeek

+0

おそらくスピードアップの可能性があるのは、「Week_Day」のインデックスを使用している可能性があります。[:= 0L、(日)] ' はこれを行うには、「日」を意味し、私はあまりにも季節の変数を追加するにはあなたのソリューションを使用しましたが、間違い' DT1によって新しい変数を追加するとき、私は「日」の周りに括弧を省略 – jangorecki

+0

@docendo変数は残っていて、私はゼロを期待していたNAを持っていました。あなたは括弧を追加することは何を知っていますか?ちょうど私は何が起こっているのかを正確に理解することができます。ブラケットを追加することによりおかげ – MidnightDataGeek

4

は、ここまでの速度で一つの試みです。私のマシンで - -

+0

私は、このような方法で ':='で変数の作成を「ベクトル化」することが可能であることを知りませんでした。本当にクールなテクニック。 – lmo

+1

確かに、RHSは最初にLHSの長さにリサイクルされ、次に行数にリサイクルされます(便宜上)。 – Arun

+0

@Arunありがとう!これは私のマシンでも驚くほど速かった。 'ユーザシステムが経過しました ' ' 0.03 0.00 0.03' 私は非常にネストされたループがかなりあるので、私のスクリプトは非常に非効率的でなければならないことが分かりました。私はある時点で別の質問を掲示します。 あなたの助けをありがとう:) – MidnightDataGeek

関連する問題