【发布时间】:2021-02-09 16:44:44
【问题描述】:
我正在尝试从字符串输入动态创建和评估函数,并且再次挂断元编程/评估 (https://adv-r.hadley.nz/metaprogramming.html)。我有一种感觉,这是在 SO 上回答的,但我搜索并无法通过其他帖子找出解决方案;但是,如果有现有答案,请告诉我并标记为重复。非常感谢您的时间和帮助!以下是该问题的表述。
library(dplyr)
library(purrr)
library(rlang)
library(palmerpenguins)
# Create data to join with penguins
penguin_colors <-
tibble(
species = c("Adelie", "Chinstrap", "Gentoo"),
color = c("orange", "purple", "green")
)
# Create function to do specified join and print join type
foo <- function(JOINTYPE) {
# DOESN'T RUN
# JOINTYPE_join(penguins, penguin_colors, by = "species")
# call2(sym(paste0(JOINTYPE, "_join")), x = penguins, y = penguin_colors, by = "species")
print(JOINTYPE)
}
# Desired behavior of foo when JOINTYPE == "inner"
inner_join(penguins, penguin_colors, by = "species")
#> # A tibble: 344 x 9
#> species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g
#> <chr> <fct> <dbl> <dbl> <int> <int>
#> 1 Adelie Torge… 39.1 18.7 181 3750
#> 2 Adelie Torge… 39.5 17.4 186 3800
#> 3 Adelie Torge… 40.3 18 195 3250
#> 4 Adelie Torge… NA NA NA NA
#> 5 Adelie Torge… 36.7 19.3 193 3450
#> 6 Adelie Torge… 39.3 20.6 190 3650
#> 7 Adelie Torge… 38.9 17.8 181 3625
#> 8 Adelie Torge… 39.2 19.6 195 4675
#> 9 Adelie Torge… 34.1 18.1 193 3475
#> 10 Adelie Torge… 42 20.2 190 4250
#> # … with 334 more rows, and 3 more variables: sex <fct>, year <int>,
#> # color <chr>
print("inner")
#> [1] "inner"
# Use function in for loop
for (JOINTYPE in c("inner", "left", "right")) {
foo(JOINTYPE)
}
#> [1] "inner"
#> [1] "left"
#> [1] "right"
# Use function in vectorised fashion
walk(c("inner", "left", "right"), foo)
#> [1] "inner"
#> [1] "left"
#> [1] "right"
由reprex package (v0.3.0) 于 2020 年 10 月 27 日创建
【问题讨论】:
-
做一个理智和安全的方法:只需使用
foo <- switch(JOINTYPE, inner = inner_join, <...>); foo(penguins, penguin_colors, by = "species") -
一般来说,非标准评估和动态函数编程变得相当麻烦,我肯定会投票给 Rolands “做一个理智和安全的方法”,因为它不应该在工业环境中占有一席之地。然而,一种选择是将函数名称创建为字符串并使用
parse(text = [function text])或get([function text], mode = 'function')提取函数以供稍后调用。 -
感谢您的 cmets!
switch肯定更直接;但是我的情况比 reprex 复杂一些,所以get和rlang::exec工作。
标签: r tidyverse metaprogramming non-standard-evaluation