【问题标题】:Row operations on selected columns based on substring in data.table根据 data.table 中的子字符串对选定列进行行操作
【发布时间】:2017-06-15 14:22:37
【问题描述】:

我想将一个函数应用于匹配两个不同子字符串的选定列。我找到了这个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]

【问题讨论】:

  • Y 的期望输出是-9, -8, -7, -6, -5

标签: r data.table rowwise


【解决方案1】:

我们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)]

【讨论】:

    【解决方案2】:

    rowSums 和rowMeans 结合grep 可以做到这一点。

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

    【讨论】:

    • 感谢您的回答。但是,解决方案 (a) 必须使用 := 运算符以充分利用 data.table 的快速性能,并且 (2) 它必须灵活地处理其他操作,而不是我在这里使用的 mean 和 sum只是为了简单
    • 好吧,这是有道理的。不过,要保留这个答案,因为它可能对不需要您添加到原始问题的附加功能的人有所帮助。
    • 当然!再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 2015-09-11
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 2017-12-23
    相关资源
    最近更新 更多