根据R中现有变量的差异和比率创建多个变量

Create multiple variables based on difference and ratios of existing variables in R

我想在我的数据集中同时创建现有变量的多个差异和比率(在这种特殊情况下,但这可以是任何东西)。我的想法是创建我想要使用的变量列表(分别是根,因为它简化了很多任务),并使用它进一步使用 data.table 方法在一行中创建所有内容。

这是一个有两个根的简单示例,以显示我正在寻找的内容。想法是执行以下操作

setDT(dataset)[ , root1.xy_diff := root1.x - root1.y]
setDT(dataset)[ , root1.xy_ratio := root1.x / root1.y]

setDT(dataset)[ , root2.xy_diff := root2.x - root2.y]
setDT(dataset)[ , root2.xy_ratio := root2.x / root2.y]

我想做得很好,使用一行,而不是每次使用新根复制粘贴相同的行。我可以为 10 个变量做到这一点,但不能为数千个变量做到这一点。那不是很聪明。

如上所示,我准备了数据集,我想要计算 difference/ratio 的变量始终具有相同的根。根据我在网上可以找到的内容,我正在考虑做类似以下的事情(使用相同的根 - 差异是值 x 和值 y 之间的差异,比率是 x 和 y 之间的比率):

roots <- c("root1","root2")
roots.x <- paste0(roots,".x")
roots.y <- paste0(roots,".y")
names <- c(paste0(roots,".xy_diff"), paste0(roots,".xy_ratio"))

dataset[ , (names) := list(difference(), ratio())]

or

dataset[ , c(paste0(roots,".xy_diff"), paste0(roots,".xy_ratio")) := lapply(.SD, list_of_functions), .SDcols=roots]

问题是,无论我尝试什么,都无济于事......我确实不知道应该怎么写。

如有必要,我可以添加一些数据。谢谢

可能有更优雅的解决方案,但这个可行:

library("data.table")
dataset <- data.table(root1.x = 1:3, root1.y = 4:2, root2.x = 5:7, root2.y = 9:7)
difference <- function(root) lapply(root, function(z) paste0("get('", z, ".x') - get('", z, ".y')"))
ratio <- function(root) lapply(root, function(z) paste0("get('", z, ".x') / get('", z, ".y')"))
roots <- c("root1","root2")

dataset[ , c(paste0(roots,".xy_diff"), paste0(roots,".xy_ratio")) := 
           lapply(c(difference(roots), ratio(roots)), function(x) eval(parse(text = x)))]

给出:

dataset[]
   root1.x root1.y root2.x root2.y root1.xy_diff root2.xy_diff root1.xy_ratio root2.xy_ratio
1:       1       4       5       9            -3            -4      0.2500000      0.5555556
2:       2       3       6       8            -1            -2      0.6666667      0.7500000
3:       3       2       7       7             1             0      1.5000000      1.0000000

您可以将数据变长,按组执行计算,然后再将数据变宽:

library("data.table")
dataset <- data.table(id = 1:3, root1.x = 1:3, root1.y = 4:2, root2.x = 5:7, root2.y = 9:7)
dtlong = melt(dataset,id.vars = "id",  measure.vars = patterns("root"), value.name = "root", variable.name = "variable")
dtlong[, c("varname", "ind"):=tstrsplit(variable, "\.")]
dtlong[, `:=`(diff = root[ind=="x"] - root[ind=="y"],
              ratio = root[ind=="x"]/root[ind=="y"])
       , by = .(varname, id)]
dt_wide = dcast(dtlong, id~varname + ind, value.var = c("root", "diff", "ratio"))

给出:

   id root_root1_x root_root1_y root_root2_x root_root2_y diff_root1_x diff_root1_y diff_root2_x diff_root2_y ratio_root1_x ratio_root1_y ratio_root2_x ratio_root2_y
1:  1            1            4            5            9           -3           -3           -4           -4     0.2500000     0.2500000     0.5555556     0.5555556
2:  2            2            3            6            8           -1           -1           -2           -2     0.6666667     0.6666667     0.7500000     0.7500000
3:  3            3            2            7            7            1            1            0            0     1.5000000     1.5000000     1.0000000     1.0000000