2016-07-22 71 views
2

設置我有一個數據表,我想爲每一個獨特的一天,一個新列,然後每個地方白天列名稱匹配行中指定1快速環路與data.table和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行,雖然它並不需要很長時間來執行(下同),長腳本的一部分,我有好幾個低效的循環,所以我我試圖讓整體運行時間縮短。

的時間來運行:

user system elapsed 
0.99 0.06 1.05 

在此先感謝。

+0

不要看'model.matrix()'爲好。也許通過使用你想要的東西。 – abhiieor

+1

相關問題:http://stackoverflow.com/q/18881073/ – Frank

回答

4

這裏有一個不同的方法是,執行得更好 - 我的機器上 - 比問題

1)原來的做法獲得獨特的天,週日除外

​​

2)初始化新的列以0:

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'上的索引使用,因爲它似乎我們多次對其進行子集化。 – jangorecki

+0

@docendo我已經使用了你的解決方案來添加季節性變量,但是我錯誤地添加了新變量''''[,(Day):= 0L]''時忽略了'Day'的括號' 這樣做意味着'Day'變量保持不變,我有NA,在那裏我會預期零。你知道添加括號是什麼嗎?只是這樣我才能明白到底發生了什麼。謝謝 – MidnightDataGeek

4

這裏是在加速一種嘗試:

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] 
} 

這實現了耦合data.table速度製成品,包括在所述第二鏈和二分搜索的ifelse與置換消除通過引用的。

+0

謝謝,@arun。我不知道以這種方式用「:=」來「變量化」創建變量是可能的。真的很酷的技術。 – lmo

+1

當然,RHS只是首先回收到LHS的長度,然後再回到行數。(爲了方便起見)。 – Arun

+0

@阿倫謝謝!這在我的機器上也非常快。 'user system elapsed' '0.03 0.00 0.03' 我現在知道我的腳本必須非常低效,因爲我有相當多的嵌套循環。我將在某個時候發佈另一個問題。 感謝您的幫助:) – MidnightDataGeek