将 n *表达式 * 的列表应用于数据框的每一行?
Apply a list of n *expressions* to each row of a dataframe?
简而言之,我有一个要应用于数据框每一行的表达式列表。这与 this question 非常相似,但有一个细微的区别,我没有 函数列表 ,但有 表达式列表 。这是我正在尝试的:
我有一个等式项的数据框,我将其传递给 paste
以形成表达式的文本字符串:
# build a test dataframe
a <- c(10, 11, 12)
b <- c(0.5, 06, 0.7)
c <- c(300, 400, 500)
d <- c(1000, 2000, NA)
p <- c(1.32, 1.37, 1.43)
m <- c(0.45, .55, .65)
params <- data.frame(a, b, c, d, p, m)
# create vector of expressions
ff.txt <- paste(params$a, "*2 + ",
params$b, "*3 + ",
params$c, "*4 + ",
params$d, "*5 * ",
"x * ",
params$p, " * ",
params$m,
sep = "")
这将return一个表达式向量存储为文本,例如“10*2 + 0.5*3 + 300*4 + 1000*5 * x * 1.32 * 0.45”。
然后我编写了一个函数,使用 parse
:
将文本表达式转换为 R 表达式
funs.list <- lapply(funs.txt, function(x) parse(file = "", text = x))
... 其中 funs.txt
是存储为文本的表达式向量。
现在,这就是我遇到困难的地方。假设 funs.list
包含两个表达式。如果我这样做:
lapply(funs.list, eval, envir = list(x=c(7, 60)))
... 我得到一个 2x2 矩阵,我只希望答案在对角线上。 (最终我将有大约 1,000 个表达式将作为优化的一部分被重复调用,因此不需要额外的计算工作。)
我尝试过的另一种方法是:
mapply(do.call, funs.list, lapply(params, list))
...但我从 do.call
收到一条错误消息,指出 'what' must be a character string or a function
。
关于从这里去哪里有什么建议吗?
如果我没理解错的话,您想用 x 的第一个值计算第一个表达式,用第二个值计算第二个表达式,依此类推。
你可以这样做:
mapply(function(ex, x) eval(ex, envir = list(x = x)), funs.list[1:2], c(7, 60))
我觉得定义一个与您的代数表达式相对应的自定义 R 函数并在行模式下使用 apply()
函数会是一个更好的设计决策(您在原始文件中似乎忽略了这一点问题)。此函数也将 x
作为输入,因此我也 cbind
将 x
向量指向原始数据框。
exp <- function(a, b, c, d, p, m, x) {
result <- 2*a + 3*b + 4*c + 5*d*x*p*m
return(result)
}
x <- c(1, 2, 3)
params <- cbind(params, x)
output <- apply(params, 1, function(x) {
exp(x['a']], x['b'], x['c'], x[["d"]],
x['p'], x['m'], x['x'])
})
简而言之,我有一个要应用于数据框每一行的表达式列表。这与 this question 非常相似,但有一个细微的区别,我没有 函数列表 ,但有 表达式列表 。这是我正在尝试的:
我有一个等式项的数据框,我将其传递给 paste
以形成表达式的文本字符串:
# build a test dataframe
a <- c(10, 11, 12)
b <- c(0.5, 06, 0.7)
c <- c(300, 400, 500)
d <- c(1000, 2000, NA)
p <- c(1.32, 1.37, 1.43)
m <- c(0.45, .55, .65)
params <- data.frame(a, b, c, d, p, m)
# create vector of expressions
ff.txt <- paste(params$a, "*2 + ",
params$b, "*3 + ",
params$c, "*4 + ",
params$d, "*5 * ",
"x * ",
params$p, " * ",
params$m,
sep = "")
这将return一个表达式向量存储为文本,例如“10*2 + 0.5*3 + 300*4 + 1000*5 * x * 1.32 * 0.45”。
然后我编写了一个函数,使用 parse
:
funs.list <- lapply(funs.txt, function(x) parse(file = "", text = x))
... 其中 funs.txt
是存储为文本的表达式向量。
现在,这就是我遇到困难的地方。假设 funs.list
包含两个表达式。如果我这样做:
lapply(funs.list, eval, envir = list(x=c(7, 60)))
... 我得到一个 2x2 矩阵,我只希望答案在对角线上。 (最终我将有大约 1,000 个表达式将作为优化的一部分被重复调用,因此不需要额外的计算工作。)
我尝试过的另一种方法是:
mapply(do.call, funs.list, lapply(params, list))
...但我从 do.call
收到一条错误消息,指出 'what' must be a character string or a function
。
关于从这里去哪里有什么建议吗?
如果我没理解错的话,您想用 x 的第一个值计算第一个表达式,用第二个值计算第二个表达式,依此类推。
你可以这样做:
mapply(function(ex, x) eval(ex, envir = list(x = x)), funs.list[1:2], c(7, 60))
我觉得定义一个与您的代数表达式相对应的自定义 R 函数并在行模式下使用 apply()
函数会是一个更好的设计决策(您在原始文件中似乎忽略了这一点问题)。此函数也将 x
作为输入,因此我也 cbind
将 x
向量指向原始数据框。
exp <- function(a, b, c, d, p, m, x) {
result <- 2*a + 3*b + 4*c + 5*d*x*p*m
return(result)
}
x <- c(1, 2, 3)
params <- cbind(params, x)
output <- apply(params, 1, function(x) {
exp(x['a']], x['b'], x['c'], x[["d"]],
x['p'], x['m'], x['x'])
})