代码之家  ›  专栏  ›  技术社区  ›  Indrajeet Patil

正确计算列表列中的“rlang”表达式

  •  0
  • Indrajeet Patil  · 技术社区  · 6 年前

    using `rlang` for conditional labelling in `ggplot` using `ggrepel` ),解决了我在自定义函数中遇到的问题,该函数在标记数据点时使用表达式过滤数据。但这个答案提出了另一个我不知道如何解决的问题。

    下面是使用的自定义函数 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>
    

    标签.var 经验 未指定,如何解决此问题?

    创建日期:2018-08-31 reprex package (v0.2.0.9000)。

    1 回复  |  直到 6 年前
        1
  •  1
  •   AndS.    6 年前

    所以我们在这里编辑函数,使过滤更加灵活。

    # 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 package (第0.2.0版)。