基于 data.table 中子字符串的选定列的行操作

Row operations on selected columns based on substring in data.table

我想将一个函数应用于匹配两个不同子字符串的选定列。我找到了这个 但我无法从那里得到答案。

这是我失败尝试的可重现示例。为了这个例子,我想做一个逐行操作,我对所有以字符串 v 开头的列的值求和,然后从以 f 开头的所有列中的值的平均值中减去.

更新: 建议的解决方案必须 (a) 使用 := 运算符以充分利用 data.table 快速性能,并且 (2) 是灵活的其他操作而不是 meansum,我在这里使用只是为了简单

library(data.table)

# generate data
  dt <- data.table(id= letters[1:5],
                   v1= 1:5, 
                   v2= 1:5,
                   f1= 11:15,
                   f2= 11:15)

dt
#>    id v1 v2 f1 f2
#> 1:  a  1  1 11 11
#> 2:  b  2  2 12 12
#> 3:  c  3  3 13 13
#> 4:  d  4  4 14 14
#> 5:  e  5  5 15 15

# what I've tried
  dt[, Y := sum( .SDcols=names(dt) %like% "v" ) - mean( .SDcols=names(dt) %like% "f" ) by = id]

rowSumsrowMeans 结合 grep 可以完成这个。

dt$Y <- rowMeans(dt[,grep("f", names(dt)),with=FALSE]) - rowSums(dt[,grep("v", names(dt)),with=FALSE])

我们melt将数据集转化为'long'格式,利用measure参数,得到'v'和sum的区别'f' 的 mean,按 'id' 分组,将 on 与原始数据集的 'id' 列连接起来,并分配 (:=) 'V1'作为'Y'变量

dt[melt(dt, measure = patterns("^v", "^f"), value.name = c("v", "f"))[
         , sum(v) - mean(f), id], Y :=V1,  on = .(id)]

dt
#   id v1 v2 f1 f2  Y
#1:  a  1  1 11 11 -9
#2:  b  2  2 12 12 -8
#3:  c  3  3 13 13 -7
#4:  d  4  4 14 14 -6
#5:  e  5  5 15 15 -5

或者另一种选择是在创建索引或 'v' 和 'f' 列后使用 Reduce

nmv <- which(startsWith(names(dt), "v"))
nmf <- which(startsWith(names(dt), "f"))
l1 <- length(nmv)
dt[, Y := Reduce(`+`, .SD[, nmv, with = FALSE])- (Reduce(`+`, .SD[, nmf, with  = FALSE])/l1)]