加速此循环以创建具有data.table的虚拟列并在R中设置

Mid*_*eek 4 performance r model.matrix data.table dummy-variable

我有一个数据表,我想为每个唯一的日创建一个新列,然后在每一行中为每天匹配列名称分配1

我使用for循环完成了这个,但我想知道是否有任何方法使用data.table和set来优化它?

这是一个例子

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)]
    }
}
Run Code Online (Sandbox Code Playgroud)

我的表是298k行,虽然它不需要很长时间执行(下面),它是一个长脚本的一部分,我有相当多的低效循环,所以我试图让整个运行时间缩短.

运行时间:

user  system elapsed
0.99    0.06    1.05
Run Code Online (Sandbox Code Playgroud)

提前致谢.

tal*_*lat 6

这是一种不同的方法,在我的机器上比在问题中的原始方法表现更好

1)获得除星期日以外的独特日子

Day <- setdiff(dt$Week_Day, "Sunday")
Run Code Online (Sandbox Code Playgroud)

2)用0初始化新列:

dt[, (Day) := 0L]
Run Code Online (Sandbox Code Playgroud)

3)在循环中通过引用更新为1:

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

简单的性能比较:

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
Run Code Online (Sandbox Code Playgroud)