问题描述
我试图根据两组变量max-width
和c1,c2,and c3
的值创建一系列变量a1,a2,and a3
。下面的代码显示了一个硬编码的解决方案,但实际上我不知道变量集的总数,例如b1,b2,and b3
和an
。如您所见,bn
变量的名称取决于c
和a
变量的名称。
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