Anu*_*nuj 4 performance if-statement r data.table
我正在编写一个函数,其中多个ifelse用于数据表操作.虽然我使用数据表来提高速度但是多个ifelse使我的代码变慢并且此功能适用于大型数据集.因此,我想知道iflese是否有替代品.来自函数的一个示例iflese(接近15 iflese),在此示例中,如果x为空,则将flag设置为1,否则为0.
dt<-dt[,flag:=ifelse(is.na(x)|!nzchar(x),1,0)]
Run Code Online (Sandbox Code Playgroud)
最快的方法可能取决于您的数据是什么样的.评论中提到的那些在这个例子中都是可比较的:
(twice由@DavidArenburg提及;以及onceadd@akrun.我不确定如何使用replications> 1 对这些进行基准测试,因为在基准测试期间实际修改了对象.)
DT <- data.table(x=sample(c(NA,"",letters),1e8,replace=TRUE))
DT0 <- copy(DT)
DT1 <- copy(DT)
DT2 <- copy(DT)
DT3 <- copy(DT)
DT4 <- copy(DT)
DT5 <- copy(DT)
DT6 <- copy(DT)
DT7 <- copy(DT)
library(rbenchmark)
benchmark(
ifelse = DT0[,flag:=ifelse(is.na(x)|!nzchar(x),1L,0L)],
keyit = {
setkey(DT1,x)
DT1[,flag:=0L]
DT1[J(NA_character_,""),flag:=1L]
},
twiceby = DT2[, flag:= 0L][is.na(x)|!nzchar(x), flag:= 1L,by=x],
twice = DT3[, flag:= 0L][is.na(x)|!nzchar(x), flag:= 1L],
onceby = DT4[, flag:= +(is.na(x)|!nzchar(x)), by=x],
once = DT5[, flag:= +(is.na(x)|!nzchar(x))],
onceadd = DT6[, flag:= (is.na(x)|!nzchar(x))+0L],
oncebyk = {setkey(DT7,x); DT7[, flag:= +(is.na(x)|!nzchar(x)), by=x]},
replications=1
)[1:5]
# test replications elapsed relative user.self
# 1 ifelse 1 19.61 31.127 17.32
# 2 keyit 1 0.63 1.000 0.47
# 6 once 1 3.26 5.175 2.68
# 7 onceadd 1 3.24 5.143 2.88
# 5 onceby 1 1.81 2.873 1.75
# 8 oncebyk 1 0.91 1.444 0.82
# 4 twice 1 3.17 5.032 2.79
# 3 twiceby 1 3.45 5.476 3.16
Run Code Online (Sandbox Code Playgroud)
讨论.在这个例子中,keyit是最快的.但是,它也是最冗长的,它会改变表的排序.此外,keyitOP的问题非常具体(利用恰好两个字符值符合条件的事实is.na(x)|!nzchar(x)),因此对于其他应用程序来说可能不太好,因为它需要写成类似的东西
keyit = {
setkey(DT1,x)
flagem = DT1[,some_other_condition(x),by=x][(V1)]$x
DT1[,flag:=0L]
DT1[J(flagem),flag:=1L]
}
Run Code Online (Sandbox Code Playgroud)