按两组查找唯一计数

Find Unique Counts By Two Groups

这是一个两部分问题:

首先,我有一组正在处理请求的用户。

User    Voucher Number  System Entry Date   Queue Entry Date    Queue Exit Date
user1   100004  8/11/2016 10:40 8/11/2016 10:40 8/11/2016 14:48
user2   100004  8/11/2016 10:40 8/11/2016 14:48 8/12/2016 16:11
user1   100004  8/11/2016 10:40 8/12/2016 16:11 8/18/2016 16:09
user3   100004  8/11/2016 10:40 8/18/2016 16:09 8/18/2016 16:11
user1   100004  8/11/2016 10:40 8/18/2016 16:11 10/12/2016 10:07
user2   100004  8/11/2016 10:40 10/12/2016 10:07    10/13/2016 13:34
user3   100004  8/11/2016 10:40 10/13/2016 14:57    10/13/2016 14:57
user4   1030003 8/18/2016 9:45  8/22/2016 16:02 8/24/2016 11:41
user2   1030003 8/18/2016 9:45  8/24/2016 11:41 8/29/2016 18:40
user1   1030003 8/18/2016 9:45  8/29/2016 18:40 8/29/2016 18:54
user1   1030003 8/18/2016 9:45  8/29/2016 18:54 8/29/2016 18:54

最终我需要量化 Queue Entry Date 每天处理的请求数量。问题是有时请求被用户关闭并由同一用户重新打开。如最后两行所示。

如果 "user""Queue Entry Date" 与上一行相同,则第二个实例将被删除。

我开发了一个 for 循环来检查这个,但我有两个问题:

(1) 循环非常慢,并且 (2) 说我有一张凭证被同一用户连续打开和关闭 3 次或更多次,我不完全确定程序将如何处理这个。

最终我需要 table 看起来像这样:

代金券计数将是根据 'Queue Entry Date'

处理的代金券数量
User    date    voucher count
user1   8/11/2016   3
user2   8/11/2016   2
user3   8/11/2016   2
user4   8/11/2016   0
user1   8/12/2016   1
user2   8/12/2016   1
user3   8/12/2016   0
user4   8/12/2016   1




df <- structure(list(User = structure(c(1L, 2L, 1L, 3L, 1L, 2L, 3L, 
4L, 2L, 1L, 1L), .Label = c("    user1", "    user2", "    user3", 
"    user4"), class = "factor"), Voucher.Number = c(100004L, 
100004L, 100004L, 100004L, 100004L, 100004L, 100004L, 1030003L, 
1030003L, 1030003L, 1030003L), System.Entry.Date = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("8/11/2016 10:40", 
"8/18/2016 9:45"), class = "factor"), Queue.Entry.Date = structure(c(3L, 
4L, 5L, 6L, 7L, 1L, 2L, 8L, 9L, 10L, 11L), .Label = c("10/12/2016 10:07", 
"10/13/2016 14:57", "8/11/2016 10:40", "8/11/2016 14:48", "8/12/2016 16:11", 
"8/18/2016 16:09", "8/18/2016 16:11", "8/22/2016 16:02", "8/24/2016 11:41", 
"8/29/2016 18:40", "8/29/2016 18:54"), class = "factor"), Queue.Exit.Date = structure(c(4L, 
5L, 6L, 7L, 1L, 2L, 3L, 8L, 9L, 10L, 10L), .Label = c("10/12/2016 10:07", 
"10/13/2016 13:34", "10/13/2016 14:57", "8/11/2016 14:48", "8/12/2016 16:11", 
"8/18/2016 16:09", "8/18/2016 16:11", "8/24/2016 11:41", "8/29/2016 18:40", 
"8/29/2016 18:54"), class = "factor")), .Names = c("User", "Voucher.Number", 
"System.Entry.Date", "Queue.Entry.Date", "Queue.Exit.Date"), class = "data.frame", row.names = c(NA, 
-11L))

这是我用来过滤的循环:

counter = 0
filtDf = data.frame()
for (elem in 1:nrow(df)){

  if (counter >0){
    curElementId <- df[counter,c(4,12)]
    prev <- df[elem,c(4,12)]
    if (curElementId[1,1] == prev[1,1] & curElementId[1,2] == prev[1,2]){
      filtDf <- rbind(filtDf,df[elem,])
    }
    else{
      filtDf <- rbind(filtDf,df[elem,])
    }
  }
  counter = counter + 1
}

然后使用以下创建频率 table:

filtDf$date<- as.POSIXct(filtDf$Queue.Exit.Date,format="%d/%d/%Y %H:%M")
filtDf$date <- as.character( round(filtDf$date , "day" ) )

dd <- ddply( filtDf , .(Queue.Entry.Date,User) , summarise , Count = length(User) )

这应该有效。首先,它使用 lubrdidate 中的 mdy_hm 将所有日期列转换为实际的日期时间对象(我同意@Frank 上面的评论),然后按条目日期时间排序以确保它是有序的。接下来,它使用 lag 检查某行是否与用户和条目日期的前一行匹配。请注意,它将为第一个条目提供 NA,我们需要确保不排除该条目,因此我使用 replace_natidyr 将第一个条目切换为 FALSE。然后,仅保留未被过滤器捕获的那些,并按日期 count

df %>%
  mutate_at(vars(System.Entry.Date, Queue.Entry.Date, Queue.Exit.Date)
            , mdy_hm) %>%
  mutate(toFilt = (User == lag(User) &
                     as.Date(Queue.Entry.Date) == lag(as.Date(Queue.Entry.Date)) ) ) %>%
  replace_na(replace = list(toFilt = FALSE)) %>%
  filter(!toFilt) %>%
  count(User, Date = as.Date(Queue.Entry.Date))

Returns:

        User       Date     n
      <fctr>     <date> <int>
1      user1 2016-08-11     1
2      user1 2016-08-12     1
3      user1 2016-08-18     1
4      user1 2016-08-29     1
5      user2 2016-08-11     1
6      user2 2016-08-24     1
7      user2 2016-10-12     1
8      user3 2016-08-18     1
9      user3 2016-10-13     1
10     user4 2016-08-22     1

请注意,这 匹配您的示例输出,但您的示例输出与您发布的数据不匹配。所以,我不确定那里发生了什么。如果你想找回 0 类,你可以使用 complete:

df %>%
  mutate_at(vars(System.Entry.Date, Queue.Entry.Date, Queue.Exit.Date)
            , mdy_hm) %>%
  arrange(Queue.Entry.Date) %>%
  mutate(toFilt = (User == lag(User) &
                     as.Date(Queue.Entry.Date) == lag(as.Date(Queue.Entry.Date)) ) ) %>%
  replace_na(replace = list(toFilt = FALSE)) %>%
  filter(!toFilt) %>%
  count(User, Date = as.Date(Queue.Entry.Date)) %>%
  complete(User, Date = full_seq(Date, 1), fill = list(n = 0))

如果您不想包含范围内的所有日期,只需使用 Date 而不是 full_seq 函数。