r-将数据变量作为对象或字符串传递给函数环境变量



使用这个玩具函数-只是dplyr::select:的包装

select_col <- function(df, chosen_col) {

if(is.character(enquo(chosen_col))){
df %>%
select(all_of(chosen_col))
} else {
df %>%
select({{ chosen_col }})
}
}

它所做的是允许选择传递给chosen_col的列,而不管该列是作为屏蔽为环境变量的数据变量还是作为屏蔽为环保变量的字符串。

这两者都返回相同的东西:

mtcars %>% 
select_col(chosen_col = mpg) %>% 
head(2)
mpg
Mazda RX4      21
Mazda RX4 Wag  21
mtcars %>% 
select_col(chosen_col = "mpg") %>% 
head(2)
mpg
Mazda RX4      21
Mazda RX4 Wag  21

虽然select_col有效,但我想要的是类似这样的东西不起作用

select_col_desired <- function(df, chosen_col) {

if(is.character(enquo(chosen_col))){
chosen_col <- convert_to_env_variable(chosen_col)
}
df %>%
select({{ chosen_col }})
}

我可以用什么来代替不存在的函数convert_to_env_variable,使select_col_desired返回与select_col相同的东西?

我知道select已经在函数之外完成了这项工作。

解决方案1:单列

如果你真的想要convert_to_env_variable()这样的东西,你可以从rlang::enquo()开始,跳过条件。

select_col_desired <- function(df, chosen_col) {

chosen_col <- enquo(chosen_col)

df %>%
select(!!chosen_col)
}

见鬼,你可以完全跳过enquo()!!

select_col_desired <- function(df, chosen_col) {
df %>%
select({{ chosen_col }})
}

这是因为;卷曲的";运算符CCD_ 12首先捕获传递给CCD_;在将结果代入其自己的位置之前,在这里作为df的上下文中的数据变量进行评估。

结果

不管怎样,你都会得到这个:

# With column as unquoted symbol.
mtcars %>% 
select_col_desired(chosen_col = mpg) %>% 
head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21

# With column as string.
mtcars %>% 
select_col_desired(chosen_col = "mpg") %>% 
head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21

解决方案2:任意选择

对于更通用的解决方案,您可以简单地将列作为...传递给select():

select_any_desired <- function(df, ...) {
df %>% select(...)
}

结果

# With column as unquoted symbol.
mtcars %>% 
select_col_desired(mpg) %>% 
head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21

# With column as string.
mtcars %>% 
select_col_desired("mpg") %>% 
head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21

备注

如果您正在编写一个包,您自然需要@import或限定rlang::enquo()magrittr:`%>%`()dplyr::select()等函数;而不是使用CCD_ 21。

步骤1:获取变量的名称

这是通过as.character(substitute(chosen_col))完成的,我们还想将其保存到步骤2。

varname <- as.character(substitute(chosen_col))

步骤2:分配到不同的环境

可以使用assign(x, value, envir=parent.frame())进行分配。在这里,使用parent.frame()作为分配环境是至关重要的,因为我们希望在函数之外进行分配,而默认行为是分配到当前环境。这里的另一个选项是分配给具有envir=globalenv的全局环境。

这将我们引向

assign(varname, x, envir=parent.frame())

其中CCD_ 26包含我们想要分配的所有内容。将其读作varname <- x

放两个步骤

select_col <- function(df, chosen_col) {
if(is.character(enquo(chosen_col))){
x <- df %>%
select(all_of(chosen_col))
} else {
x <- df %>%
select({{ chosen_col }})
}
varname <- as.character(substitute(chosen_col))
assign(varname, x, envir=parent.frame())
x
}
select_col(mtcars, "mpg") %>% head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21
head(mpg, 2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21
rm(mpg)
select_col(mtcars, mpg) %>% head(2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21
head(mpg, 2)
#>               mpg
#> Mazda RX4      21
#> Mazda RX4 Wag  21

最新更新