首页 文章

将dplyr链转换为函数

提问于
浏览
1

给定一列日期,这将计算每个月的记录数

library(dplyr)
library(lubridate)

samp <- tbl_df(seq.Date(as.Date("2017-01-01"), as.Date("2017-12-01"), by="day"))

freq <- samp %>%
    filter(!is.na(value)) %>% 
    transmute(month = floor_date(value, "month")) %>%
    group_by(month) %>% summarise(adds = n())


freq
# A tibble: 12 x 2
        month  adds
       <date> <int>
 1 2017-01-01    31
 2 2017-02-01    28
 3 2017-03-01    31
 4 2017-04-01    30
 5 2017-05-01    31
 6 2017-06-01    30
 7 2017-07-01    31
 8 2017-08-01    31
 9 2017-09-01    30
10 2017-10-01    31
11 2017-11-01    30
12 2017-12-01     1
>

我想将其转换为函数,以便我可以对许多变量执行操作 . 已经阅读了关于dplyr编程的小插图,但仍然存在问题 .

我的尝试;

library(rlang)
count_x_month <- function(df, var, name){
    var <- enquo(var)
    name <- enquo(name)

    df %>%
    filter(!is.na(!!var)) %>% 
    transmute(month := floor_date(!!var, "month")) %>%
    group_by(month) %>% summarise(!!name := n())
} 

freq2 <- samp %>% count_x_month(value, out)

错误信息;

Error: invalid argument type

使这个版本的功能工作将是一个很大的帮助 . 更广泛地说,欢迎实现该目标的其他方式 . 陈述问题的一种方法;给定客户数据框和首次购买日期,计算每个月第一次购买的客户数量 .

更新:所选答案适用于dplyr 0.7.4,但我可以访问的rstudio环境有dplyr 0.5.0 . “后退”此功能需要进行哪些修改?

3 回答

  • 0

    你忘了 quo_name

    library(rlang)
    count_x_month <- function(df, var, name){
      var <- enquo(var)
      name <- enquo(name)
      name <- quo_name(name)
    
      df %>%
        filter(!is.na(!!var)) %>% 
        transmute(month := floor_date(!!var, "month")) %>%
        group_by(month) %>% 
        summarise(!!name := n())
    } 
    
    freq2 <- samp %>% count_x_month(value, out)
    
    # A tibble: 12 x 2
            month   out
           <date> <int>
     1 2017-01-01    31
     2 2017-02-01    28
     3 2017-03-01    31
     4 2017-04-01    30
     5 2017-05-01    31
     6 2017-06-01    30
     7 2017-07-01    31
     8 2017-08-01    31
     9 2017-09-01    30
    10 2017-10-01    31
    11 2017-11-01    30
    12 2017-12-01     1
    

    请参阅“Programming with dplyr”的"Different input and output variable"部分:

    我们通过将字符串粘贴在一起来创建新名称,因此我们需要使用quo_name()将输入表达式转换为字符串 .

  • 0

    该错误是由 summarise(df, !!name := n()) 引起的,并通过替换函数的第二行来解决

    name <- substitute(name)
    

    据我所知,原因在于它不仅仅是它的名字,而且还带有来自它的环境 . 在函数中指定列名时这是有意义的 . 该函数必须知道列来自哪个数据框(在这种情况下为环境)以用值替换名称 .

    但是, name 应采用用户指定的新名称 . 没有什么可以替代它 . 我怀疑如果使用 name <- enquo(name) ,R想要用值替换 !!name 而不是仅仅输入新名称 . 因此它抱怨在LHS上没有名字(因为R用值(?)代替)

    但不确定 substitute 是否是意识形态的"programming with dplyr"方式 . 欢迎评论 .

  • 2

    创建一个显示客户ID和首次购买日期的数据框:

    dates <- seq.Date(as.Date("2017-01-01"), as.Date("2017-12-01"), by="day")
    dates_rep <- c(dates,dates,dates)
    cust_ids <- paste('id_', floor(runif(length(dates_rep), min=0, max=100000)))
    cust_frame <- data.frame(ID=cust_ids, FP_DATE=dates_rep)
    
    head(cust_frame)
    

    enter image description here

    使用plyr包按FP_DATE聚合:

    library(plyr)
    count(cust_frame, c('FP_DATE'))
    

    因此,给定客户数据框和首次购买日期,我们会计算每个月第一次购买的客户数量 .

    enter image description here

    您可以对此进行扩展以聚合数据集中的任意数量的要素:

    count(cust_frame, c('FP_DATE', 'feature_b', 'feature_c', 'feature_d', 'feature_e'))
    

相关问题