动态地将特定函数应用于不同的变量
Dynamically apply a specific function to different variables
我有一个 csv,每个变量定义一行(指的是在另一个数据集中定义的真实数据变量)。轻轻按摩后,我有一个命名向量,如 fxs
.
然后我可以迭代变量,并执行适当的函数。我应该考虑另一种方法吗?也许使用 rlang::exec()
and/or purrr::map_*()
. I like that I can wrap the two main lines with separate tryCatch()
块可以更准确地描述是在解析函数时出错,还是在执行函数时出错。
fxs <- c(
"Sepal.Length" = "\(x) x * 1",
"Sepal.Width" = "\(x) x * 10",
"Petal.Length" = "\(x) x * 100"
)
d <- iris[1:5, 1:3]
for (variable in colnames(d)) {
fx <- base::eval(base::parse(text = fxs[[variable]]))
d[[variable]] <- fx(d[[variable]])
}
d
我认为它看起来很像 dplyr::mutate()
语句的内部。也许最好尝试将 csv 转换为传递给 ...
的语句。除了这个概念验证之外,我没有做任何事情,所以如果有人有不同的方法,我有很大的灵活性。
d |>
dplyr::mutate(
Sepal.Length = Sepal.Length * 1,
Sepal.Width = Sepal.Width * 10,
Petal.Length = Petal.Length * 100,
)
期望的输出:
Sepal.Length Sepal.Width Petal.Length
1 5.1 35 140
2 4.9 30 140
3 4.7 32 130
4 4.6 31 150
5 5.0 36 140
我们可以使用 cur_column()
对 across
内的表达式进行子集化
library(dplyr)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(fxs)),
.fns = ~ eval(parse(text = fxs[[dplyr::cur_column()]]))(.x)
)
)
-输出
Sepal.Length Sepal.Width Petal.Length
1 5.1 35 140
2 4.9 30 140
3 4.7 32 130
4 4.6 31 150
5 5.0 36 140
或使用exec
library(purrr)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(fxs)),
.fns = ~ rlang::exec(
rlang::parse_expr(fxs[[dplyr::cur_column()]]),
.x
)
)
)
如果函数都在进行乘法运算,则创建一个命名的 vector
或 list
值进行相乘,并避免 eval/parse
nm1 <- c(Sepal.Length = 1, Sepal.Width = 10, Petal.Length = 100)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(nm1)),
.fns = ~ nm1[dplyr::cur_column()] * .x
)
)
我有一个 csv,每个变量定义一行(指的是在另一个数据集中定义的真实数据变量)。轻轻按摩后,我有一个命名向量,如 fxs
.
然后我可以迭代变量,并执行适当的函数。我应该考虑另一种方法吗?也许使用 rlang::exec()
and/or purrr::map_*()
. I like that I can wrap the two main lines with separate tryCatch()
块可以更准确地描述是在解析函数时出错,还是在执行函数时出错。
fxs <- c(
"Sepal.Length" = "\(x) x * 1",
"Sepal.Width" = "\(x) x * 10",
"Petal.Length" = "\(x) x * 100"
)
d <- iris[1:5, 1:3]
for (variable in colnames(d)) {
fx <- base::eval(base::parse(text = fxs[[variable]]))
d[[variable]] <- fx(d[[variable]])
}
d
我认为它看起来很像 dplyr::mutate()
语句的内部。也许最好尝试将 csv 转换为传递给 ...
的语句。除了这个概念验证之外,我没有做任何事情,所以如果有人有不同的方法,我有很大的灵活性。
d |>
dplyr::mutate(
Sepal.Length = Sepal.Length * 1,
Sepal.Width = Sepal.Width * 10,
Petal.Length = Petal.Length * 100,
)
期望的输出:
Sepal.Length Sepal.Width Petal.Length
1 5.1 35 140
2 4.9 30 140
3 4.7 32 130
4 4.6 31 150
5 5.0 36 140
我们可以使用 cur_column()
对 across
library(dplyr)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(fxs)),
.fns = ~ eval(parse(text = fxs[[dplyr::cur_column()]]))(.x)
)
)
-输出
Sepal.Length Sepal.Width Petal.Length
1 5.1 35 140
2 4.9 30 140
3 4.7 32 130
4 4.6 31 150
5 5.0 36 140
或使用exec
library(purrr)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(fxs)),
.fns = ~ rlang::exec(
rlang::parse_expr(fxs[[dplyr::cur_column()]]),
.x
)
)
)
如果函数都在进行乘法运算,则创建一个命名的 vector
或 list
值进行相乘,并避免 eval/parse
nm1 <- c(Sepal.Length = 1, Sepal.Width = 10, Petal.Length = 100)
d %>%
dplyr::mutate(
dplyr::across(
.cols = dplyr::all_of(names(nm1)),
.fns = ~ nm1[dplyr::cur_column()] * .x
)
)