在具有函数参数命名变量的函数中使用 pivot_wider

Using pivot_wider in a function with named variable from function argument

我正在尝试在函数内部使用 pivot_wider。这些值不是唯一定义的,所以我需要指定 pivot_wider 的 values_fn 参数,它应该 return 一个列表。 values_fn 的列是函数的参数。

这是一个最小的例子:

library(rlang)
library(tidyverse)

t <- tibble::tibble(a = c(rep("A", 2), rep("B", 3), "C"), 
                    b = seq(1:6))

# This works without a function
t %>% tidyr::pivot_wider(names_from = a, 
                         values_from = b, 
                         values_fn =  list(b = list))

# Now I want to do the same with a function. But the := is not valid in the values_fn.

pivot_func <- function(dat, name_col, value_col){
  dat %>% 
    tidyr::pivot_wider(names_from = {{name_col}}, 
                       values_from = {{value_col}}, 
                       values_fn = list({{value_col}} := list))
}

pivot_func(t, a, b)

Error: ":=" can only be used within a quasiquoted argument Run "rlang::last_error()" to see where the error occurred.

错误提示您在 non-quasiquoted 参数中使用了 :=。这是因为您在函数 list 中使用它。您还使用 {{values_from}},但您的函数没有名为 values_from.

的参数

相反,您可以在管道之前创建您需要的函数列表并将其传递给 values_fn:

pivot_func <- function(dat, name_col, value_col){
  fns <- setNames(list(list), deparse(substitute(value_col)))
  dat %>% 
    tidyr::pivot_wider(names_from = {{name_col}}, 
                       values_from = {{value_col}}, 
                       values_fn = fns)
}

pivot_func(t, a, b)
#> # A tibble: 1 x 3
#>   A         B         C        
#>   <list>    <list>    <list>   
#> 1 <int [2]> <int [3]> <int [1]>

或者,如果您想坚持使用 rlang 语法,您可以这样做:

pivot_func <- function(dat, name_col, value_col){
  
  dat %>% 
    tidyr::pivot_wider(names_from = {{name_col}}, 
                       values_from = {{value_col}}, 
                       values_fn = setNames(list(list), 
                                            expr_deparse(enexpr(value_col))))
}

做同样的事情。