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

时间:2020-08-26 18:21:53

标签: r for-loop data.table purrr

我试图根据两组变量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创建

4 个答案:

答案 0 :(得分:4)

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

anames <- grep("^a[0-9]+$", colnames(DT), value = TRUE)
bnames <- grep("^b[0-9]+$", colnames(DT), 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

答案 1 :(得分:4)

如果先按名称模式按列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

答案 2 :(得分:2)

我们可以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

答案 3 :(得分:2)

基本R选项

u<-split.default(DT,gsub("\\D","",names(DT)))
cbind(DT,do.call(cbind,Map(rowSums,setNames(u,paste0("c",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