正确评估列表列内的 rlang 表达式
properly evaluating `rlang` expression inside list column
这是 () 的后续问题,它解决了我在自定义函数中遇到的问题,该函数使用表达式在标记数据点时过滤掉数据。但是这个答案提出了另一个我不知道如何解决的问题。
这是自定义函数,它使用 rlang
计算用户输入的表达式以过滤掉数据,同时将标签附加到数据点。当不在列表列内使用时,此功能可以正常工作。例如-
# loading needed libraries
library(tidyverse)
library(ggplot2)
library(ggrepel)
# custom function
label_adder <- function(data, x, y, label.var, exp = NULL) {
param_list <- as.list(match.call())
if ("exp" %in% names(param_list)) {
my_exp <- rlang::enquo(exp)
}
else {
a <- "dplyr::row_number(x = .) > 0"
my_exp <- rlang::quo(!!rlang::sym(a))
}
plot <-
ggplot(mapping = aes(
x = !!rlang::enquo(x),
y = !!rlang::enquo(y)
)) +
geom_point(data = data) +
geom_smooth(data = data, method = "lm") +
geom_label_repel(
data = data %>% filter(!!my_exp),
mapping = aes(label = !!rlang::enquo(label.var))
)
return(plot)
}
# using the function
label_adder(
data = datasets::iris,
x = Sepal.Length,
y = Sepal.Width,
label.var = Species,
exp = Sepal.Length > 7
)
但是当我使用与purrr::map
相同的函数时,它失败了。
# creating a list column
df.listcol <- datasets::iris %>%
dplyr::mutate(.data = ., Species2 = Species) %>% # just creates a copy of this variable
dplyr::group_by(.data = ., Species) %>%
tidyr::nest(data = .)
# running function on dataframe with list columns
df.listcol %>% # creates a nested dataframe with list column called `data`
dplyr::mutate( # creating a new list column of ggstatsplot outputs
.data = .,
plot = data %>%
purrr::map(
.x = .,
.f = ~label_adder(
data = .,
x = Sepal.Length,
y = Sepal.Width
)
)
)
#> Error in mutate_impl(.data, dots): Evaluation error: Evaluation error: object 'dplyr::row_number(x = .) > 0' not found..
但是如果我通过指定 label.var
和 exp
使用该函数,它就可以正常工作。
# running function on dataframe with list columns
df.listcol %>% # creates a nested dataframe with list column called `data`
dplyr::mutate( # creating a new list column of ggstatsplot outputs
.data = .,
plot = data %>%
purrr::map(
.x = .,
.f = ~label_adder(
data = .,
x = Sepal.Length,
y = Sepal.Width,
label.var = Species,
exp = Sepal.Length > 7
)
)
)
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 x 5]> <S3: gg>
#> 2 versicolor <tibble [50 x 5]> <S3: gg>
#> 3 virginica <tibble [50 x 5]> <S3: gg>
所以我的问题是为什么在未指定 label.var
和 exp
时函数会失败,以及如何解决这个问题?
由 reprex package (v0.2.0.9000) 创建于 2018-08-31。
所以这里我们编辑函数,让过滤更加灵活
# loading needed libraries
library(tidyverse)
library(ggplot2)
library(ggrepel)
# custom function
label_adder <- function(data, x, y, label.var, exp = NULL) {
param_list <- as.list(match.call())
label_data <- data %>% {if ("exp" %in% names(param_list)) filter(., !!enquo(exp)) else .}
plot <-
ggplot(mapping = aes(
x = !!rlang::enquo(x),
y = !!rlang::enquo(y)
)) +
geom_point(data = data) +
geom_smooth(data = data, method = "lm") +
geom_label_repel(
data = label_data,
mapping = aes(label = !!rlang::enquo(label.var))
)
return(plot)
}
df.listcol <- datasets::iris %>%
dplyr::mutate(.data = ., Species2 = Species) %>% # just creates a copy of this variable
dplyr::group_by(.data = ., Species) %>%
tidyr::nest(data = .)
test <- df.listcol %>% mutate(plot = map(data, ~label_adder(., x = Sepal.Length, label.var = Species2, y = Sepal.Width)))
test
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 × 5]> <S3: gg>
#> 2 versicolor <tibble [50 × 5]> <S3: gg>
#> 3 virginica <tibble [50 × 5]> <S3: gg>
test$plot[[2]]
test2 <- df.listcol %>% mutate(plot = map(data, ~label_adder(., x = Sepal.Length, label.var = Species2, y = Sepal.Width, exp = Sepal.Length > 6.5)))
test2
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 × 5]> <S3: gg>
#> 2 versicolor <tibble [50 × 5]> <S3: gg>
#> 3 virginica <tibble [50 × 5]> <S3: gg>
test2$plot[[2]]
由 reprex 创建于 2018-08-31
包 (v0.2.0).
这是 (
这是自定义函数,它使用 rlang
计算用户输入的表达式以过滤掉数据,同时将标签附加到数据点。当不在列表列内使用时,此功能可以正常工作。例如-
# loading needed libraries
library(tidyverse)
library(ggplot2)
library(ggrepel)
# custom function
label_adder <- function(data, x, y, label.var, exp = NULL) {
param_list <- as.list(match.call())
if ("exp" %in% names(param_list)) {
my_exp <- rlang::enquo(exp)
}
else {
a <- "dplyr::row_number(x = .) > 0"
my_exp <- rlang::quo(!!rlang::sym(a))
}
plot <-
ggplot(mapping = aes(
x = !!rlang::enquo(x),
y = !!rlang::enquo(y)
)) +
geom_point(data = data) +
geom_smooth(data = data, method = "lm") +
geom_label_repel(
data = data %>% filter(!!my_exp),
mapping = aes(label = !!rlang::enquo(label.var))
)
return(plot)
}
# using the function
label_adder(
data = datasets::iris,
x = Sepal.Length,
y = Sepal.Width,
label.var = Species,
exp = Sepal.Length > 7
)
但是当我使用与purrr::map
相同的函数时,它失败了。
# creating a list column
df.listcol <- datasets::iris %>%
dplyr::mutate(.data = ., Species2 = Species) %>% # just creates a copy of this variable
dplyr::group_by(.data = ., Species) %>%
tidyr::nest(data = .)
# running function on dataframe with list columns
df.listcol %>% # creates a nested dataframe with list column called `data`
dplyr::mutate( # creating a new list column of ggstatsplot outputs
.data = .,
plot = data %>%
purrr::map(
.x = .,
.f = ~label_adder(
data = .,
x = Sepal.Length,
y = Sepal.Width
)
)
)
#> Error in mutate_impl(.data, dots): Evaluation error: Evaluation error: object 'dplyr::row_number(x = .) > 0' not found..
但是如果我通过指定 label.var
和 exp
使用该函数,它就可以正常工作。
# running function on dataframe with list columns
df.listcol %>% # creates a nested dataframe with list column called `data`
dplyr::mutate( # creating a new list column of ggstatsplot outputs
.data = .,
plot = data %>%
purrr::map(
.x = .,
.f = ~label_adder(
data = .,
x = Sepal.Length,
y = Sepal.Width,
label.var = Species,
exp = Sepal.Length > 7
)
)
)
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 x 5]> <S3: gg>
#> 2 versicolor <tibble [50 x 5]> <S3: gg>
#> 3 virginica <tibble [50 x 5]> <S3: gg>
所以我的问题是为什么在未指定 label.var
和 exp
时函数会失败,以及如何解决这个问题?
由 reprex package (v0.2.0.9000) 创建于 2018-08-31。
所以这里我们编辑函数,让过滤更加灵活
# loading needed libraries
library(tidyverse)
library(ggplot2)
library(ggrepel)
# custom function
label_adder <- function(data, x, y, label.var, exp = NULL) {
param_list <- as.list(match.call())
label_data <- data %>% {if ("exp" %in% names(param_list)) filter(., !!enquo(exp)) else .}
plot <-
ggplot(mapping = aes(
x = !!rlang::enquo(x),
y = !!rlang::enquo(y)
)) +
geom_point(data = data) +
geom_smooth(data = data, method = "lm") +
geom_label_repel(
data = label_data,
mapping = aes(label = !!rlang::enquo(label.var))
)
return(plot)
}
df.listcol <- datasets::iris %>%
dplyr::mutate(.data = ., Species2 = Species) %>% # just creates a copy of this variable
dplyr::group_by(.data = ., Species) %>%
tidyr::nest(data = .)
test <- df.listcol %>% mutate(plot = map(data, ~label_adder(., x = Sepal.Length, label.var = Species2, y = Sepal.Width)))
test
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 × 5]> <S3: gg>
#> 2 versicolor <tibble [50 × 5]> <S3: gg>
#> 3 virginica <tibble [50 × 5]> <S3: gg>
test$plot[[2]]
test2 <- df.listcol %>% mutate(plot = map(data, ~label_adder(., x = Sepal.Length, label.var = Species2, y = Sepal.Width, exp = Sepal.Length > 6.5)))
test2
#> # A tibble: 3 x 3
#> Species data plot
#> <fct> <list> <list>
#> 1 setosa <tibble [50 × 5]> <S3: gg>
#> 2 versicolor <tibble [50 × 5]> <S3: gg>
#> 3 virginica <tibble [50 × 5]> <S3: gg>
test2$plot[[2]]
由 reprex 创建于 2018-08-31 包 (v0.2.0).