我有一个示例 data.tabledata如下:
VarName Formulae
1: A 1+1
2: B A+3
3: C B*10
4: D A+C
5: E D/2
Run Code Online (Sandbox Code Playgroud)
我想将Formulae列转换为公式,以便输出可以变成这样:
VarName Result
1: A 2
2: B 5
3: C 50
4: D 52
5: E 26
Run Code Online (Sandbox Code Playgroud)
基本上,VarName列是变量名称,Formulae列是相应的公式。
A = 1+1
B = A+3
C = B*10
D = A+C
E = D/2
Run Code Online (Sandbox Code Playgroud)
我尝试过使用eval和parse等函数data$VarName = eval(parse(text = "data$Formulae")),但是我无法获得所需的输出。
循环遍历VarName,将其替换为括号内的公式,然后计算:
res <- setNames(x$Formulae, x$VarName)
while(any(grepl(paste0(names(res), collapse = "|"), res))) {
for(i in names(res)){
res <- gsub(i, paste0("(", res[ i ], ")"), res, fixed = TRUE)
}
}
#res, after replacements:
# A B
# "1+1" "(1+1)+3"
# C D
# "((1+1)+3)*10" "(1+1)+(((1+1)+3)*10)"
# E
# "((1+1)+(((1+1)+3)*10))/2"
# evaluate
sapply(res, function(i) eval(parse(text = i)))
#A B C D E
#2 5 50 52 26
Run Code Online (Sandbox Code Playgroud)
实现此目的的一种方法是转换Formulae为实际的单方面公式,然后转换为函数,然后在函数内部依次求值,lst()从而允许顺序构建对象。这依赖于框架的元编程功能tidyverse而不是data.table.
library(dplyr)
library(purrr)
df <- data.frame(VarName = LETTERS[1:5],
Formulae = c("1+1", "A+3", "B*10", "A+C", "D/2"))
lst(!!!map(set_names(df$Formulae, df$VarName),
~ quo(
as_mapper(reformulate(.x))()
)))
$A
[1] 2
$B
[1] 5
$C
[1] 50
$D
[1] 52
$E
[1] 26
Run Code Online (Sandbox Code Playgroud)
或者:
lst(!!!set_names(df$Formulae, df$VarName) %>% map(str2lang))
Run Code Online (Sandbox Code Playgroud)
正如下面的评论中所指出的,这些要求公式按顺序排列。