正确评估列表列内的`rlang`表达式 [英] properly evaluating `rlang` expression inside list column
问题描述
这是对((v0.2.0.9000)创建于2018年8月31日.
因此,在这里我们编辑函数以使过滤更加灵活.
#加载所需的库图书馆(tidyverse)库(ggplot2)图书馆(ggrepel)#自定义函数label_adder<-函数(数据,x,y,label.var,exp = NULL){param_list<-as.list(match.call())label_data<-数据%>%{if((exp"%in%names(param_list))filter(.,!! enquo(exp))else.}情节<-ggplot(映射= aes(x = !! rlang :: enquo(x),y = !! rlang :: enquo(y)))+geom_point(数据=数据)+geom_smooth(数据=数据,方法="lm")+geom_label_repel(数据= label_data,映射= aes(标签= !! rlang :: enquo(label.var)))回报(情节)}df.listcol<-数据集:: iris%>%dplyr :: mutate(.data =.,Species2 = Species)%&%;%#仅创建此变量的副本dplyr :: group_by(.data =.,种)%>%tidyr :: nest(data =.)测试<-df.listcol%>%变异(plot = map(data,〜label_adder(.,x = Sepal.Length,label.var = Species2,y = Sepal.Width)))测试#>#小动作:3 x 3#>物种数据图#>< fct>< list>< list>#>1setosa< tibble [50×5]>< S3:gg>#>2杂色< tibble [50×5]>< S3:gg>#>3 virginica< tibble [50×5]>< S3:gg>test $ plot [[2]]
test2<-df.listcol%>%mutate(图= map(data,〜label_adder(.,x = Sepal.Length,label.var = Species2,y = Sepal.Width,exp =分隔长度> 6.5)))测试2#>#小动作:3 x 3#>物种数据图#>< fct>< list>< list>#>1setosa< tibble [50×5]>< S3:gg>#>2杂色< tibble [50×5]>< S3:gg>#>3 virginica< tibble [50×5]>< S3:gg>test2 $ plot [[2]]
由 reprex创建于2018-08-31包(v0.2.0).
This is a follow-up question to (using `rlang` for conditional labelling in `ggplot` using `ggrepel`), which solved the problem I was facing in a custom function using an expression to filter out data while labeling data points. But the answer raised another issue that I don't know how to solve.
Here is the custom function that uses rlang
to evaluate the user-entered expression to filter out data while attaching labels to data points. And this function works fine when not used inside list columns. For example-
# 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
)
But when I use the same function with purrr::map
, it fails.
# 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..
But if I use the function by specifying label.var
and exp
, it works just fine.
# 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>
So my question is why the function fails when label.var
and exp
are not specified and how to resolve this issue?
Created on 2018-08-31 by the reprex package (v0.2.0.9000).
So here we edit the function to make the filtering more flexible.
# 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]]
Created on 2018-08-31 by the reprex package (v0.2.0).
这篇关于正确评估列表列内的`rlang`表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!