【问题标题】:Conditionally calculating average time between events by group in R在R中按组有条件地计算事件之间的平均时间
【发布时间】:2021-05-21 10:06:21
【问题描述】:

我正在处理来自电话热线服务的通话记录数据集。有三种呼叫结果:已应答、已放弃和已参与。我试图找出每个呼叫者在放弃上一个呼叫后再次联系热线所花费的平均时间。时差可以是秒、分钟、小时或天,但如果可能的话,我希望得到所有四个。

这是一些我正在使用的变量的模拟数据:-


library(wakefield)#for generating the Status variable
library(dplyr)
library(stringi)
library(Pareto)
library(uuid)

n_users<-1300
n_rows <- 365000

set.seed(1)
#data<-data.frame()
Date<-seq(as.Date("2015-01-01"), as.Date("2015-12-31"), by = "1 day")
Date<-sample(rep(Date,each=1000),replace = T)

u <- runif(length(Date), 0, 60*60*12) # "noise" to add or subtract from some timepoint
CallDateTime<-as.POSIXlt(u, origin = paste0(Date,"00:00:00"))
CallDateTime

CallOutcome<-r_sample_factor(x = c("Answered", "Abandoned", "Engaged"), n=length(Date))
CallOutcome

data<-data.frame(Date,CallDateTime,CallOutcome)

relative_probs <- rPareto(n = n_users, t = 1, alpha = 0.3, truncation = 500) 
unique_ids <- UUIDgenerate(n = n_users)

data$CallerId <- sample(unique_ids, size = n_rows, prob = relative_probs, replace = TRUE)
data<-data%>%arrange(CallDateTime)

head(data)

所以重申一下,如果呼叫者放弃了他们的呼叫(在 CallOutcome 列中以“Abandoned”表示),我想知道呼叫者再次调用服务所花费的平均时间,以四个时间单位表示我已经提到了。关于我如何实现这一点的任何指示都会很棒:)

【问题讨论】:

    标签: r dplyr timestamp conditional-statements difftime


    【解决方案1】:

    首先,我将创建前导变量(基本上按组计算“下一个”值是多少。然后就像使用 difftime 的任何单位一样简单。密度图可以帮助您分析这些差异,如下图。

    data <-
     data %>% 
     group_by(CallerId) %>% 
      mutate(CallDateTime_Next = lead(CallDateTime)) %>% 
      ungroup() %>% 
      mutate(
        diff_days = difftime(CallDateTime_Next, CallDateTime, units = 'days'),
        diff_hours = difftime(CallDateTime_Next, CallDateTime, units = 'hours'),
        diff_mins = difftime(CallDateTime_Next, CallDateTime, units = 'mins'),
        diff_secs = difftime(CallDateTime_Next, CallDateTime, units = 'secs')
      )
    
    
    data %>% 
      filter(CallOutcome == 'Abandoned') %>% 
      ggplot() +
      geom_density(aes(x = diff_days))
    

    【讨论】:

      【解决方案2】:

      为每个ID 保留当前行为"Abandoned" 且下一行不是"Abandoned" 的数据中的行。查找每 2 行之间的时间差,以获取调用者在放弃后再次调用服务所需的时间,取每个持续时间的平均值以获得平均时间。

      library(dplyr)
      
      data %>%
        #Test the answer on smaller subset
        #slice(1:1000) %>%
        arrange(CallerId, CallDateTime) %>%
        group_by(CallerId) %>%
        filter(CallOutcome == 'Abandoned' & dplyr::lead(CallOutcome) != 'Abandoned' | 
                CallOutcome != 'Abandoned' & dplyr::lag(CallOutcome) == 'Abandoned') %>%
        mutate(group = rep(row_number(), each = 2, length.out = n())) %>%
        group_by(group, .add = TRUE) %>%
        summarise(avg_sec = difftime(CallDateTime[2], CallDateTime[1], units = 'secs')) %>%
        mutate(avg_sec = as.numeric(mean(avg_sec)), 
               avg_min = avg_sec/60, 
               avg_hour = avg_min/60, 
               avg_day = avg_hour/24) -> result
      
      result
      

      【讨论】:

      • 我喜欢这种方法,与我的非常相似,但您先过滤行。根据数据的大小,您的可能会更快。
      • 您好,感谢您的回复。所以这个解决方案会得到从“Abandoned”调用到下一个调用的平均时间,不管下一个调用的结果是什么,对吗?
      • 仅当下一个呼叫未被放弃时。如果呼叫订单是 Abandoned、Abandoned、Engaged。它将忽略第一个 Abandoned 并在下一个 Abandoned 和 Engaged 之间进行区分。
      • 好的,很高兴知道这一点。谢谢你。如果不是太麻烦,我必须在filter 部分更改什么以获得从放弃到下一个 CallOutcome 的平均时间(不管它是什么)?
      • 在这种情况下,您将 filter 更改为 filter(CallOutcome == 'Abandoned' &amp; dplyr::lag(CallOutcome) == 'Abandoned')
      猜你喜欢
      • 2017-05-12
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 2020-11-23
      • 1970-01-01
      • 2019-07-12
      • 2017-05-21
      相关资源
      最近更新 更多