根据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
我想在我的数据集中同时创建现有变量的多个差异和比率(在这种特殊情况下,但这可以是任何东西)。我的想法是创建我想要使用的变量列表(分别是根,因为它简化了很多任务),并使用它进一步使用 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