将dplyr链转换为函数

时间:2017-12-19 22:26:23

标签: r dplyr

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

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。对后退&#39;进行了哪些修改?这个功能?

3 个答案:

答案 0 :(得分:2)

你忘记了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”的“不同输入和输出变量”部分:

  

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

答案 1 :(得分:0)

错误是由summarise(df, !!name := n())引起的,并通过用

替换函数的第二行来解决
name <- substitute(name)

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

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

不确定substitute是否为ideomatic&#34;使用dplyr进行编程&#34;但是方式。欢迎提出意见。

答案 2 :(得分:0)

创建一个显示客户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'))