加速此循环以使用 data.table 创建虚拟列并在 R 中设置
Speed up this loop to create dummy columns with data.table and set in R
我有一个数据 table,我想为每个唯一的日期创建一个新列,然后在日期与列名称匹配的每一行中分配一个 1
我已经使用 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)]
}
}
我的 table 是 298k 行,虽然执行时间不长(下图),但它是一个长脚本的一部分,而且我有很多低效的循环,所以我试图获得整体运行时间下来了。
到 运行 的时间:
user system elapsed
0.99 0.06 1.05
提前致谢。
这是一种加速尝试:
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
。
这是一种不同的方法,在我的机器上比问题中的原始方法表现更好
1) 获取除星期日以外的唯一日期
Day <- setdiff(dt$Week_Day, "Sunday")
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
我有一个数据 table,我想为每个唯一的日期创建一个新列,然后在日期与列名称匹配的每一行中分配一个 1
我已经使用 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)]
}
}
我的 table 是 298k 行,虽然执行时间不长(下图),但它是一个长脚本的一部分,而且我有很多低效的循环,所以我试图获得整体运行时间下来了。
到 运行 的时间:
user system elapsed
0.99 0.06 1.05
提前致谢。
这是一种加速尝试:
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
。
这是一种不同的方法,在我的机器上比问题中的原始方法表现更好
1) 获取除星期日以外的唯一日期
Day <- setdiff(dt$Week_Day, "Sunday")
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