在基于data.table的其他变量名称中创建多个变量

问题描述

我试图根据两组变量max-widthc1,c2,and c3的值创建一系列变量a1,a2,and a3。下面的代码显示一个硬编码的解决方案,但实际上我不知道变量集的总数,例如b1,b2,and b3an。如您所见,bn变量的名称取决于ca变量的名称

b中是否有办法做到这一点?我尝试通过在data.table中使用purrr::map2来做到这一点,但无法使其正常工作。非常感谢您的帮助。

谢谢。

data.table

reprex package(v0.3.0)于2020-08-26创建

解决方法

第一部分主要是防御性的,谨防:a*个变量而不匹配b*个变量;反之亦然;以及每个顺序的不同:

anames <- grep("^a[0-9]+$",colnames(DT),value = TRUE)
bnames <- grep("^b[0-9]+$",value = TRUE)
numnames <- gsub("^a","",anames)
anames <- sort(anames[gsub("^a",anames) %in% numnames])
bnames <- sort(bnames[gsub("^b",bnames) %in% numnames])
cnames <- gsub("^b","c",bnames)

如果您知道数字在先验范围内,并且希望动态性更小但更简单明了,那么

anames <- paste0("a",1:3)
bnames <- paste0("b",1:3)
cnames <- paste0("c",1:3)

现在神奇了:

DT[,(cnames) := Map(`+`,mget(anames),mget(bnames)) ]
DT
#    a1 a2 a3 b1 b2 b3 c1 c2 c3
# 1:  1  2  3  5 20 25  6 22 28
# 2:  2  4  6  6 24 30  8 28 36
# 3:  3  6  9  7 28 35 10 34 44
,

如果先按名称模式按列DT拆分,然后对其进行汇总,则可以解决此问题

# removes numbers from col names
(ptn <- sub("\\d",names(DT))) 
# [1] "a" "a" "a" "b" "b" "b"

# get unique numbers contained in the col names (as strings but it doesn't matter here)
(nmb <- unique(sub("\\D",names(DT))))
# [1] "1" "2" "3"

下一步是拆分DT,最后进行汇总

DT[,paste0("c",nmb) := do.call(`+`,split.default(DT,f = ptn))]

结果

DT
#   a1 a2 a3 b1 b2 b3 c1 c2 c3
#1:  1  2  3  5 20 25  6 22 28
#2:  2  4  6  6 24 30  8 28 36
#3:  3  6  9  7 28 35 10 34 44
,

我们可以melt转换为长格式,创建列“ c”,将dcast转换为“宽”格式,然后cbind

library(data.table)
cbind(DT,dcast(melt(DT,measure = patterns('^a','^b'))[,c := value1 + value2],rowid(variable) ~ paste0('c',variable),value.var = 'c')[,variable := NULL])
#   a1 a2 a3 b1 b2 b3 c1 c2 c3
#1:  1  2  3  5 20 25  6 22 28
#2:  2  4  6  6 24 30  8 28 36
#3:  3  6  9  7 28 35 10 34 44
,

基本R选项

u<-split.default(DT,gsub("\\D",names(DT)))
cbind(DT,do.call(cbind,Map(rowSums,setNames(u,names(u))))))

给出

   a1 a2 a3 b1 b2 b3 c1 c2 c3
1:  1  2  3  5 20 25  6 22 28
2:  2  4  6  6 24 30  8 28 36
3:  3  6  9  7 28 35 10 34 44