如何用循环高效生成data.table的dummy变量?原循环失效求助
问题与解决方案
问题背景
需要批量生成以原变量名_dummy命名的二值变量,原手动实现代码如下:
library(data.table) set.seed(3199) var1 <- rnorm(100, 0, 0.1) var2 <- rnorm(100, -45, 12) var3 <- rnorm(100, 4, 56) vars <- data.table(cbind(var1, var2, var3)) vars <- vars[, var1_dummy := ifelse(var1 > 0, 1, 0)] vars <- vars[, var2_dummy := ifelse(var2 > 0, 1, 0)] vars <- vars[, var3_dummy := ifelse(var3 > 0, 1, 0)]
尝试的循环代码未达到预期效果:
set.seed(3199) var1 <- rnorm(100, 0, 0.1) var2 <- rnorm(100, -45, 12) var3 <- rnorm(100, 4, 56) vars <- data.table(cbind(var1, var2, var3)) for (i in c(var1, var2, var3)){ vars <- vars[, i_dummy := ifelse(i > 0, 1, 0)] }
错误原因
- 循环遍历的是变量的数值向量而非变量名,无法关联data.table中的目标列,且新列名固定为
i_dummy,无法生成对应原变量名的后缀。 - 每次循环重新赋值整个data.table,违背了data.table的高效原地修改逻辑。
正确解法
解法1:data.table向量化批量处理(最优,最高效)
利用data.table的.SD和lapply实现无循环批量生成,完全贴合data.table的高效设计:
library(data.table) set.seed(3199) var1 <- rnorm(100, 0, 0.1) var2 <- rnorm(100, -45, 12) var3 <- rnorm(100, 4, 56) vars <- data.table(var1, var2, var3) # 直接构造data.table,比cbind更高效 # 批量生成所有dummy列 vars[, paste0(names(vars), "_dummy") := lapply(.SD, function(x) as.integer(x > 0))]
names(vars)获取所有原变量名,paste0拼接_dummy后缀得到新列名.SD代表当前选中的所有列(默认全列),lapply遍历每一列生成0/1二值as.integer(x > 0)替代ifelse,逻辑值转整数直接得到1/0,更简洁高效:=操作实现原地修改,无需重新赋值整个data.table,性能更优
解法2:正确的循环写法(若需使用循环)
若必须用循环,需遍历变量名而非变量值,同时利用data.table的引用修改:
library(data.table) set.seed(3199) var1 <- rnorm(100, 0, 0.1) var2 <- rnorm(100, -45, 12) var3 <- rnorm(100, 4, 56) vars <- data.table(var1, var2, var3) # 遍历所有变量名 for (col_name in names(vars)) { new_col <- paste0(col_name, "_dummy") # 动态命名列并赋值 vars[, (new_col) := as.integer(get(col_name) > 0)] }
- 循环遍历
names(vars)获取每个原变量名 (new_col)将字符串转为列名,实现动态命名get(col_name)在data.table环境中获取对应列的值- 同样使用
as.integer(x > 0)替代ifelse提升效率
内容的提问来源于stack exchange,提问作者derhard
相关产品推荐
相关产品推荐

