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

时间:2017-06-15 14:22:37

标签: r data.table rowwise

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

以下是我尝试失败的可重复示例。为了这个例子,我想做一个逐行操作,我将所有列中的值与字符串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]

2 个答案:

答案 0 :(得分:2)

我们melt将数据集转换为“长”格式,通过使用measure参数,获得sum'v'和mean之间的差异'f',按'id'分组,将'id'列与原始数据集加入on,并将':=)'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)]

答案 1 :(得分:0)

rowSumsrowMeansgrep相结合可以实现此目的。

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