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

如何在data.table中高效利用多列值自定义函数计算新列

高效实现data.table中动态列的自定义行计算

我在用data.table处理包含多列的数据集,需要根据部分列的值为每行计算专属新列。简单函数可以用.SDcols实现,但遇到需要区分列值处理的自定义逻辑时就比较麻烦。

数据集结构

Training Age  Client1 Stim1.0 Stim1.1  Client2 Stim2.0 Stim2.1 Choice Val.00 Val.01
1:        0   1  absence       0       0  absence       0       0      2      0      0
2:        0   2  absence       0       0  absence       0       0      2      0      0
3:        0   3 Object 1       1       1 Object 2       2       2      1      0      0
4:        0   4 Object 2       2       1 Object 2       2       1      1      0      0
5:        0   5  absence       0       0  absence       0       0      2      0      0
6:        0   6  absence       0       0  absence       0       0      2      0      0
   Val.02 alpha.0 Val.10 Val.11 Val.12 alpha.1 V25
1: 0.0000   0.005      0 0.0000 0.0000   0.005  NA
2: 0.0000   0.005      0 0.0000 0.0000   0.005  NA
3: 0.0025   0.005      0 0.0000 0.0025   0.005  NA
4: 0.0050   0.005      0 0.0025 0.0025   0.005  NA
5: 0.0050   0.005      0 0.0025 0.0025   0.005  NA
6: 0.0050   0.005      0 0.0025 0.0025   0.005  NA

小列数场景的实现(fcase)

当Stim和Val列数量较少时,可以直接用fcase硬编码实现:

rawData[,`:=`(Val.Client1=fcase(Stim1.0==0,Val.00,
                               Stim1.0==1,Val.01,Stim1.0==2,Val.02)+
                fcase(Stim1.1==0,Val.10,
                      Stim1.1==1,Val.11,Stim1.1==2,Val.12),
              Val.Clien2=fcase(Stim2.0==0,Val.00,
                               Stim2.0==1,Val.01,Stim2.0==2,Val.02)+
                fcase(Stim2.1==0,Val.10,
                      Stim2.1==1,Val.11,Stim2.1==2,Val.12))]

当前通用但低效的实现(apply+.SDcols)

由于不同数据集的列数不固定,我写了通用代码,但用apply逐行处理速度极慢:

numSti<-2; numFeat<-2 # 定义预期的列数参数
rawData[,Val.Client1:=apply(.SD,MARGIN = 1,FUN = function(x){
  x<-as.numeric(x) # 必须强制转为数值型
  Stim1.tmp<-x[1:numSti]+1 # 提取Stim相关列的值并调整索引
  vals<-x[(numSti*2+1): (numSti*2+numSti*(1+numFeat))] # 提取Val相关列的值
  locVal<-Stim1.tmp+(numFeat+1)*(0:(numSti-1)) # 映射Stim值到对应的Val列索引
  return(sum(vals[locVal])) # 对选中的Val值求和
}),.SDcols=patterns("Stim.|Val.")]

数据集dput输出

as.data.table(structure(list(Age = 1:6, Client1 = c(2L, 2L, 0L, 1L, 2L, 2L), 
    Stim1.0 = c(0L, 0L, 1L, 2L, 0L, 0L), Stim1.1 = c(0L, 0L, 
    1L, 1L, 0L, 0L), Client2 = c(2L, 2L, 1L, 1L, 2L, 2L), Stim2.0 = c(0L, 
    0L, 2L, 2L, 0L, 0L), Stim2.1 = c(0L, 0L, 2L, 1L, 0L, 0L), 
    Choice = c(2L, 2L, 1L, 1L, 2L, 2L), Val.00 = c(0, 0, 0, 0, 
    0, 0), Val.01 = c(0, 0, 0, 0, 0, 0), Val.02 = c(0, 0, 0.0025, 
    0.005, 0.005, 0.005), alpha.0 = c(0.005, 0.005, 0.005, 0.005, 
    0.005, 0.005), Val.10 = c(0, 0, 0, 0, 0, 0), Val.11 = c(0, 
    0, 0, 0.0025, 0.0025, 0.0025), Val.12 = c(0, 0, 0.0025, 0.0025, 
    0.0025, 0.0025), alpha.1 = c(0.005, 0.005, 0.005, 0.005, 
    0.005, 0.005), V25 = c(NA, NA, NA, NA, NA, NA)), row.names = c(NA, 
-6L), class = c("data.table", "data.frame")))

求高效的通用解决方案,能避免逐行处理的性能问题。


内容的提问来源于stack exchange,提问作者Andres Eduardo Quiñones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:35:15