如何将不带引号的列名列表馈送到'lapply'(以便我可以将其与'dplyr'函数一起使用)

如何将不带引号的列名列表馈送到'lapply'(以便我可以将其与'dplyr'函数一起使用),r,dplyr,tidyverse,rlang,lazyeval,R,Dplyr,Tidyverse,Rlang,Lazyeval,我正在尝试在tidyverse/dplyr中编写一个函数,我希望最终与lappy(或map)一起使用。(我一直在研究它,但发现了一个有趣的结果/死胡同。请不要将此标记为重复-此问题是对您在那里看到的答案的延伸/偏离。) 是否有 1)获取引用变量列表以在dplyr函数中工作的方法 (并且不要使用不推荐使用的SE函数)或者是否存在 2)通过lappy或map 我已经使用了vignette来构建我认为最符合当前标准的函数 感谢与NSE合作 样本数据: 在将字符串列表交给apply和map之前,我还尝试

我正在尝试在
tidyverse/dplyr
中编写一个函数,我希望最终与
lappy
(或
map
)一起使用。(我一直在研究它,但发现了一个有趣的结果/死胡同。请不要将此标记为重复-此问题是对您在那里看到的答案的延伸/偏离。)

是否有
1)获取引用变量列表以在dplyr函数中工作的方法
(并且不要使用不推荐使用的
SE
函数)或者是否存在
2)通过
lappy
map

我已经使用了vignette来构建我认为最符合当前标准的函数 感谢与NSE合作

样本数据: 在将字符串列表交给
apply
map
之前,我还尝试将其转换为名称:

library(rlang)
cat.names <- lapply(cat.list, sym)
lapply(cat.names, report)
map_df(cat.names, report)
在任何情况下,我问这个问题的原因是我认为我已经按照当前文档化的标准编写了函数,但最终我看不到任何方法可以利用
apply
的成员,甚至
purr::map
家族的成员来使用这样的函数。除了像用户在这里所做的那样重写函数以使用
名称
,还有没有办法让此函数与
应用
映射
一起工作

我希望看到这样的结果:

#一个tible:27 x 5
#分组:报告_值[16]
报告值年度总数报告类别
1 J 2014财年1 25报告代码
2016财年第2季度1 1报告代码
2017财年第3季度1100份报告代码
4 R 2017财年1 50报告代码
5 R 2018财年2 75报告代码
6 S 2017财年2400报告代码
2018财年7 S 2530报告代码
8检查2014财年1 25付款方法
9检查2017财年1 50的付款方式
10检查2018财年2 55的付款方法
# ... 还有17排

我不是一个真正的dplyr爱好者,但这里的价值在于如何使用
library(data.table)
实现这一点:

setDT(sample_data)

gen_report <- function(report_cat){
  sample_data[ , .(num = .N, total = sum(AMOUNT), REPORT_CATEGORY = report_cat), 
               by = .(REPORT_VALUE = get(report_cat), YEAR)] 
}

gen_report('REPORT_CODE')
lapply(cat.list, gen_report)
setDT(样本数据)

gen_report
as.name
将字符串转换为名称,并可传递给
report

lapply(cat.list, function(x) do.call("report", list(as.name(x))))
字符参数另一种方法是重写
报告
,以便它接受字符串参数:

report_ch <- function(colname) {  
    report_cat <- rlang::sym(colname)   # as.name(colname) would also work here
    sample_data %>%
                group_by(!!report_cat, YEAR) %>%
                summarize(num = n(), total = sum(AMOUNT)) %>% 
                rename(REPORT_VALUE = !!report_cat) %>% 
                mutate(REPORT_CATEGORY = colname)
}

lapply(cat.list, report_ch)
当然,如果您使用不同的框架,整个问题都会消失,例如

plyr

library(plyr)

report_plyr <- function(colname)
  ddply(sample_data, c(REPORT_VALUE = colname, "YEAR"), function(x)
     data.frame(num = nrow(x), total = sum(x$AMOUNT), REPORT_CATEOGRY = colname))

lapply(cat.list, report_plyr)
库(plyr)

report_plyr首先让我指出,在初始的
report
函数中,您可以使用
quo_name
将quosure转换为字符串,然后在
mutate
中使用该字符串,如下所示:

library(dplyr)
library(rlang)

report <- function(report_cat){
  report_cat <- enquo(report_cat)

  sample_data %>%
    group_by(!!report_cat, YEAR) %>%
    summarize(num=n(),total=sum(AMOUNT)) %>%
    rename(REPORT_VALUE = !!report_cat) %>%
    mutate(REPORT_CATEGORY = quo_name(report_cat))
}

report(REPORT_CODE)
report(!!!syms(cat.list))
或者使用
syms
可以一次解析向量的所有元素:

map_df(syms(cat.list), ~report(!!.))
结果:

# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows 
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows
通过将
map\u df
放在
report
中,您可以利用
quos
,它将
转换为quos列表。然后,它们被送入
map_df
并使用
逐个取消引用

report(REPORT_CODE, PAYMENT_METHOD, INBOUND_CHANNEL, AMOUNT_CAT)
这样编写的另一个优点是,您还可以提供字符串符号向量,并使用
拼接它们如下所示:

library(dplyr)
library(rlang)

report <- function(report_cat){
  report_cat <- enquo(report_cat)

  sample_data %>%
    group_by(!!report_cat, YEAR) %>%
    summarize(num=n(),total=sum(AMOUNT)) %>%
    rename(REPORT_VALUE = !!report_cat) %>%
    mutate(REPORT_CATEGORY = quo_name(report_cat))
}

report(REPORT_CODE)
report(!!!syms(cat.list))
结果:

# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows 
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows
#一个tible:27 x 5
#分组:报告_值[16]
报告值年度总数报告类别
1 J 2014财年1 25报告代码
2016财年第2季度1 1报告代码
2017财年第3季度1100份报告代码
4 R 2017财年1 50报告代码
5 R 2018财年2 75报告代码
6 S 2017财年2400报告代码
2018财年7 S 2530报告代码
8检查2014财年1 25付款方法
9检查2017财年1 50的付款方式
10检查2018财年2 55的付款方法
# ... 还有17排

很好的后续问题。有关
syms
quos
这样一个全面而精心设计的解决方案集合的解释,请参见我的答案。这几天我将继续整理行李——这里有很多东西要学。非常感谢。哇,我想我已经学到了7个新东西,而你所有的解决方案我只学了一半。这么多有趣的层需要考虑。我想我已经开始认识到为什么函数式编程会以如此虔诚的语气被提及。谢谢大家!@詹斯勒森很高兴这有帮助。你每天都会学到一些东西:)
library(dplyr)
library(rlang)

report <- function(report_cat){
  report_cat <- enquo(report_cat)

  sample_data %>%
    group_by(!!report_cat, YEAR) %>%
    summarize(num=n(),total=sum(AMOUNT)) %>%
    rename(REPORT_VALUE = !!report_cat) %>%
    mutate(REPORT_CATEGORY = quo_name(report_cat))
}

report(REPORT_CODE)
library(purrr)

cat.list <- c("REPORT_CODE","PAYMENT_METHOD","INBOUND_CHANNEL","AMOUNT_CAT")

map_df(cat.list, ~report(!!sym(.)))    
map_df(syms(cat.list), ~report(!!.))
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows 
report <- function(...){
  report_cat <- quos(...)

  map_df(report_cat, function(x) sample_data %>%
             group_by(!!x, YEAR) %>%
             summarize(num=n(),total=sum(AMOUNT)) %>%
             rename(REPORT_VALUE = !!x) %>%
             mutate(REPORT_CATEGORY = quo_name(x)))
}
report(REPORT_CODE, PAYMENT_METHOD, INBOUND_CHANNEL, AMOUNT_CAT)
report(!!!syms(cat.list))
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE  YEAR   num total REPORT_CATEGORY
          <chr> <chr> <int> <int>           <chr>
 1            J  FY14     1    25     REPORT_CODE
 2            Q  FY16     1     1     REPORT_CODE
 3            Q  FY17     1   100     REPORT_CODE
 4            R  FY17     1    50     REPORT_CODE
 5            R  FY18     2    75     REPORT_CODE
 6            S  FY17     2   400     REPORT_CODE
 7            S  FY18     2   530     REPORT_CODE
 8        Check  FY14     1    25  PAYMENT_METHOD
 9        Check  FY17     1    50  PAYMENT_METHOD
10        Check  FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows