You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用data.table高效创建新变量并指定列名?

批量生成data.table等级列的简化方案

问题背景

现有如下结构的data.table数据:

structure(list(english_score = c(3L, 4L, 3L, 3L, 4L, 3L, 4L, 
2L, 4L, 2L, 3L, 3L, 2L, 2L, 3L, 4L, 3L, 3L, 4L, 3L, 4L, 3L, 2L
), math_score = c(4L, 4L, 3L, 4L, 4L, 4L, 3L, 2L, 3L, 3L, 4L, 
2L, 4L, 2L, 4L, 2L, 3L, 3L, 2L, 2L, 2L, 4L, 2L), science_score = c(3L, 
4L, 4L, 4L, 3L, 4L, 4L, 3L, 3L, 2L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 
2L, 3L, 2L, 3L, 3L, 4L)), row.names = c(NA, -23L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x000002478ee34d50>)

需要为每科分数生成对应的等级列(如english_level),等级规则通过自定义函数实现,原方法是逐个列处理,希望用data.table语法简化流程。

原自定义函数:

myfunction<-function(x){case_when(x<2~"Level A",
                              x>1 & x<3~"Level B",
                              x>2 & x<4~"Level C",
                              x>3~"Level D")}

原逐个处理代码:

DT[, english_level:=lapply(.SD, myfunction), .SDcols='english_score']
DT[, math_level:=lapply(.SD, myfunction), .SDcols='math_score']
DT[, science_level:=lapply(.SD, myfunction), .SDcols='science_score']

简化方案

方法1:批量处理多列,一步生成所有等级列

利用data.table的.SD(Subset of Data)和批量赋值特性,一次性处理所有分数列并生成对应等级列:

  1. 定义分数列列表和目标等级列名:
# 指定需要处理的分数列
score_cols <- c("english_score", "math_score", "science_score")
# 生成对应的等级列名(比如english_score → english_level)
level_cols <- paste0(sub("_score", "", score_cols), "_level")
  1. 批量赋值生成等级列:
DT[, (level_cols) := lapply(.SD, myfunction), .SDcols = score_cols]

这里(level_cols)用于将变量中的列名作为目标列,lapply(.SD, myfunction)对.SDcols指定的每一列应用自定义函数,直接生成所有等级列。

方法2:替换为data.table原生的fcase优化函数

原函数使用了dplyr::case_when,可以替换为data.table原生的fcase函数,更贴合data.table生态,执行效率也更高:

myfunction <- function(x){
  fcase(
    x < 2, "Level A",
    x > 1 & x < 3, "Level B",
    x > 2 & x < 4, "Level C",
    x > 3, "Level D"
  )
}

替换后再执行方法1的批量赋值代码即可,效果完全一致。

方法3:melt+dcast转置处理(适合更复杂的多列场景)

如果后续有更多类似列需要处理,也可以通过转长再转宽的方式实现:

# 转长格式
DT_long <- melt(DT, measure.vars = score_cols, variable.name = "subject", value.name = "score")
# 添加等级列
DT_long[, level := myfunction(score)]
# 转宽格式合并回原表
DT <- dcast(DT_long, ... ~ sub("_score", "", subject), value.var = c("score", "level"))
# 调整列名(可选,和目标结构对齐)
setnames(DT, gsub("_level", "", names(DT))[grepl("level", names(DT))], level_cols)

这种方法适合列数极多的场景,但对于当前3列的情况,方法1更简洁高效。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:05:45