我想将函数应用于与两个不同子字符串匹配的选定列。我找到了这个post related to my question,但我无法从那里得到答案。
以下是我尝试失败的可重复示例。为了这个例子,我想做一个逐行操作,我将所有列中的值与字符串v
相加,并从f
开始的所有列中的值的平均值中减去
更新:建议的解决方案必须(a)使用:=
运算符来充分利用data.table
快速性能,以及(2)对其他操作具有灵活性比mean
和sum
,我在这里仅仅是为了简单起见
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]
答案 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)
rowSums
和rowMeans
与grep
相结合可以实现此目的。
dt$Y <- rowMeans(dt[,grep("f", names(dt)),with=FALSE]) - rowSums(dt[,grep("v", names(dt)),with=FALSE])