用Dplyr编程:如何创建一个可以在for循环中使用的函数?

时间:2018-03-08 13:14:16

标签: r dplyr rlang

目标

我正在尝试创建一个创建自定义交叉表(a.k.a. pivot table)的函数。要做到这一点,我正在使用rlang包,试图坚持“dplyr”编程方式。另请参阅http://dplyr.tidyverse.org/articles/programming.html

功能

library(tidyverse)

crossTable <- function(
  df,
  rows,
  cols,
  vals
){

  quoRows = enquo(rows)
  quoCols = enquo(cols)
  quoVals = enquo(vals)

  result <-
    df %>%
    group_by(!!quoRows, !!quoCols) %>%
    summarize(
      values = !!quoVals
    ) %>%
    ungroup() %>%
    spread(!!quoCols, values)

}

什么有用

在全球环境中调用此功能。

a <- crossTable(mpg, manufacturer, cyl, mean(hwy))
a

什么行不通

我希望能够使用此函数自动为不同的rowscolsvals生成不同的交叉表,例如使用for循环或其中一个map函数(tidyverse等效于基础apply函数)。换句话说,我希望能够做到这样的事情:

b <- list()

colVars <- c(cyl, class)

expr <- c(mean(hwy), mean(cty), median(hwy), median(cty))

for(i in seq_along(colVars)){

  for(j in seq_along(expr)){

    b[[i]][[j]] <- crossTable(mpg, manufacturer, colVars[[i]], expr[[j]])

  }

}

对于rowscols我看到有些人使用group_by_at,但这仍然无法解决vals的问题。

我的问题

  • 如何更改此功能以使其在for循环中工作(或使用map / apply进行调用时)?
  • 或者,如果使用dplyr方式(使用enquo和朋友)使其工作太困难,那么解决这个问题的“基础”方法是什么?

1 个答案:

答案 0 :(得分:0)

一个选项是转换&#39; expr&#39;在quouts中然后在循环中,使用!!评估参数以及将字符向量(&#39; colVars&#39;)转换为sym(&#39; symbol&#39;)< / p>

colVars <- c("cyl", "class")
b <- vector('list', length(colVars))
expr <- quos(mean(hwy), mean(cty), median(hwy), median(cty))
for(i in seq_along(colVars)){

  for(j in seq_along(expr)){

    b[[i]][[j]] <- crossTable(mpg, manufacturer, !!rlang::sym(colVars[i]), !! expr[[j]])

  }

}

- 检查输出

identical(crossTable(mpg, manufacturer, cyl, mean(hwy)), b[[1]][[1]])
#[1] TRUE
identical(crossTable(mpg, manufacturer, cyl, mean(cty)), b[[1]][[2]])
#[1] TRUE
identical(crossTable(mpg, manufacturer, cyl, median(hwy)), b[[1]][[3]])
#[1] TRUE
identical(crossTable(mpg, manufacturer, cyl, median(cty)), b[[1]][[4]]) 
#[1] TRUE