如何在长表达式中引用数据框中的多个变量
how to reference many variables inside dataframe in long expression
我有以下df
> structure(f)
p c at cu z m A ps dc w al W b t s u re fs1 fs2 uc
1 21 7 12 43 1 0.5 10 22.3 5 5 8 NA 0.782 NA NA NA NA NA NA NA
和另一个包含 expressions/formulas 的 df 来计算 f
中的 NA 值
> structure(formulas)
W t
2 p*z*al p*z*sin(b)
s u re
2 p*z*cos(b) m*ps*z c+((s-u)*tan(at)
f 可能有多行,所以我只想将每个公式应用于每一列的所有行。
例如计算 W 我可以尝试
f$W=f$p*f$z*f$al
不过我想知道是否有办法将这一切自动化。我想转换公式中的表达式,然后应用它们来计算 f 中的相应变量。有没有一种方法可以在评估表达式时不重复 df$ 来引用 df 中的列?
我知道我可以使用 eval(parse(text="formulas[1,1]")) 将我的字符串变成一个表达式,但在这里我正在处理整个 df 列。
编辑,感谢 Frank,事实证明这种方法不必要地复杂,因为 eval
可以接受 envir
参数。
dat <- data.frame(a=1:5,b=5:1)
因此,我们可以这样写公式:
formulas = quote(data.frame(a_plus_b = a+b, a_min_b = a-b))
评估就很容易了:
out <- cbind(dat, eval(formulas, dat))
> out
a b a_plus_b a_min_b
1 1 5 6 -4
2 2 4 6 -2
3 3 3 6 0
4 4 2 6 2
5 5 1 6 4
使用字符串的旧方法:
formulas <- data.frame(a_plus_b="a+b",
a_min_b = "a-b",stringsAsFactors=F)
out <- cbind(dat,lapply(formulas, function(x){with(dat, eval(parse(text=x)))}))
这是我对这种 data.table
方式的看法。可能也可以摆脱 for 循环。但不知何故,它对我不起作用。如果我找到方法会更新。
df <- data.table(x = rnorm(10), y = rnorm(10), z = NA, w = NA)
df2 <- data.table(x = NA, y = NA, z = "cos(x) + sin(y)", w = "x * y")
varnames <- colnames(df2)[!sapply(df2[1,], is.na)]
for(i in varnames){
df[,c(i) := with(df, eval(parse(text = with(df2, get(i)))))]
}
dplyr
方式:
require(dplyr)
f <- f %>% mutate(W = p*z*al, t = p*z*sin(b), s = p*z*cos(b),
u = m*ps*z, re = c+((s-u)*tan(at))
我有以下df
> structure(f)
p c at cu z m A ps dc w al W b t s u re fs1 fs2 uc
1 21 7 12 43 1 0.5 10 22.3 5 5 8 NA 0.782 NA NA NA NA NA NA NA
和另一个包含 expressions/formulas 的 df 来计算 f
中的 NA 值> structure(formulas)
W t
2 p*z*al p*z*sin(b)
s u re
2 p*z*cos(b) m*ps*z c+((s-u)*tan(at)
f 可能有多行,所以我只想将每个公式应用于每一列的所有行。 例如计算 W 我可以尝试
f$W=f$p*f$z*f$al
不过我想知道是否有办法将这一切自动化。我想转换公式中的表达式,然后应用它们来计算 f 中的相应变量。有没有一种方法可以在评估表达式时不重复 df$ 来引用 df 中的列? 我知道我可以使用 eval(parse(text="formulas[1,1]")) 将我的字符串变成一个表达式,但在这里我正在处理整个 df 列。
编辑,感谢 Frank,事实证明这种方法不必要地复杂,因为 eval
可以接受 envir
参数。
dat <- data.frame(a=1:5,b=5:1)
因此,我们可以这样写公式:
formulas = quote(data.frame(a_plus_b = a+b, a_min_b = a-b))
评估就很容易了:
out <- cbind(dat, eval(formulas, dat))
> out
a b a_plus_b a_min_b
1 1 5 6 -4
2 2 4 6 -2
3 3 3 6 0
4 4 2 6 2
5 5 1 6 4
使用字符串的旧方法:
formulas <- data.frame(a_plus_b="a+b",
a_min_b = "a-b",stringsAsFactors=F)
out <- cbind(dat,lapply(formulas, function(x){with(dat, eval(parse(text=x)))}))
这是我对这种 data.table
方式的看法。可能也可以摆脱 for 循环。但不知何故,它对我不起作用。如果我找到方法会更新。
df <- data.table(x = rnorm(10), y = rnorm(10), z = NA, w = NA)
df2 <- data.table(x = NA, y = NA, z = "cos(x) + sin(y)", w = "x * y")
varnames <- colnames(df2)[!sapply(df2[1,], is.na)]
for(i in varnames){
df[,c(i) := with(df, eval(parse(text = with(df2, get(i)))))]
}
dplyr
方式:
require(dplyr)
f <- f %>% mutate(W = p*z*al, t = p*z*sin(b), s = p*z*cos(b),
u = m*ps*z, re = c+((s-u)*tan(at))