R将函数调用转换为另一个调用,而不使用字符串操作

问题描述 投票:0回答:1

我正在寻找一种将函数调用包装到另一个函数中的好方法。在一个函数被调用为其他函数之前将其包装是很容易的,但是对我来说修改现有的调用似乎并不那么直接。

我找到了一种方法,可以使用下面的示例进行解释,但是基本上,它依赖于将调用转换为列表并转换为字符串,然后将新调用添加为字符串,然后使用str2lang将所有内容转换回语言。

是否有一种更清洁的方法?

让我为summarise构建一个自定义dplyr函数,该函数将检查输出是否为矢量,在这种情况下,通过在现有调用上使用df-col创建一个pivot_wider(enframe(...))

这里是代表。

library(tidyverse)

short_sum <- function(data, ...) {

  fns <- rlang::enquos(...)

  fns <- purrr::map(fns, function(x) {

    res <- rlang::eval_tidy(x, data = data)

    if ((is.vector(res)  || is.factor(res)) && length(res) > 1) {

      # is there a better way to do this (start) ---
      # get expression of call and turn it into a string
      x_expr <- as.character(list(rlang::quo_get_expr(x)))

      # construct a string with expression above wrapped in another call
      x_expr <- paste0(
        "pivot_wider(enframe(",
        x_expr,
        "), names_from = name, values_from = value)"
      )

      # turn string into language and replace expression in x
      x <- rlang::quo_set_expr(x, str2lang(x_expr))
      # is there a better way to do this (end) ---

      x
    } else {
      x
    }
  })

    dplyr::summarise(data, !!! fns, .groups="drop")
}


mtcars %>% 
  as_tibble %>% 
  short_sum(quant = quantile(mpg),
            range = range(wt))

#> # A tibble: 1 x 2
#>   quant$`0%` $`25%` $`50%` $`75%` $`100%` range$`1`  $`2`
#>        <dbl>  <dbl>  <dbl>  <dbl>   <dbl>     <dbl> <dbl>
#> 1       10.4   15.4   19.2   22.8    33.9      1.51  5.42

reprex package(v0.3.0)于2020-06-14创建

此问题基于我使用上述方法的答案here

r function call rlang
1个回答
0
投票

我不确定100%该功能做什么,但我认为您可能正在寻找类似的东西:

short_sum <- function(data, ...) {

  fns <- rlang::enquos(...)

  fns <- purrr::map(fns, function(x) {
    res <- rlang::eval_tidy(x, data = data)

    if ((is.vector(res)  || is.factor(res)) && length(res) > 1) {
      rlang::expr(pivot_wider(enframe(
        !!rlang::quo_get_expr(x)), names_from = name, values_from = value))
      # or
      # bquote(pivot_wider(enframe(
      #  .(rlang::quo_get_expr(x))), names_from = name, values_from = value))
    } else {
      x
    }
  })

  dplyr::summarise(data, !!! fns, .groups="drop")
}

[expr()类似于quote(),除了可以使用!!!!!取消对表达式的部分引用。

[bquote()也类似于quote(),但在基数R中,您使用.()取消引用。

© www.soinside.com 2019 - 2024. All rights reserved.