从用户ID和时间差创建一个会话ID

4
我有一个与此问题(根据“userID”和“timeStamp”的差异创建“sessionID”)类似的问题,但我的规格略有不同。也许解决方案仍然显而易见,但我无法将其应用于我的需求——指出原始解决方案如何满足我的问题将是等效的。
我的 data.table 看起来像这样(以下是可用的dput):
unique_visitor_id        datetime            
100                 2016-07-25 15:43:02      
100                 2016-08-15 15:35:16      
101                 2016-08-01 21:24:46      
101                 2016-08-13 05:32:27      
101                 2016-08-13 05:33:01      
101                 2016-08-13 05:33:37      
101                 2016-08-13 05:34:04      
101                 2016-08-13 05:37:42      
101                 2016-08-13 05:38:20      
102                 2016-09-15 17:28:00      
102                 2016-09-15 17:31:04      
103                 2016-07-18 21:19:07 

NB: datetime已经通过ymd_hms(datetime)lubridate中被转换为日期对象。

我的需求是创建一个新的变量来识别会话,该变量是一个简单的整数序列(不需要包含visitorID,就像原始问题一样)- 只要记录是< = 30分钟且在同一天内,会话就由访问者定义。因此,例如,前两行将是两个不同的会话:尽管是同一位访问者,但时间差异大于30分钟。

以上数据的期望输出将是:

unique_visitor_id        datetime            session_id
100                 2016-07-25 15:43:02           1
100                 2016-08-15 15:35:16           2
101                 2016-08-01 21:24:46           3
101                 2016-08-13 05:32:27           4
101                 2016-08-13 05:33:01           4
101                 2016-08-13 05:33:37           4
101                 2016-08-13 05:34:04           4
101                 2016-08-13 05:37:42           4
101                 2016-08-13 05:38:20           4
102                 2016-09-15 17:28:00           5
102                 2016-09-15 17:31:04           5
103                 2016-07-18 21:19:07           6

如果可以用data.table的方式完成,那将是理想的。再次道歉,如果我在原问题的解决方案中错过了什么!

这里是dput样本数据表:

myDT <- structure(list(unique_visitor_id = c(100L, 100L, 101L, 
                                 101L, 101L, 101L, 101L, 101L, 101L, 102L, 102L, 103L), 
           datetime = structure(c(1469475782, 1471289716, 1470101086, 1471080747, 1471080781, 
                                            1471080817, 1471080844, 1471081062, 1471081100, 1473974880, 
                                            1473975064, 1468891147), 
                                          tzone = "EST5EDT", class = c("POSIXct", "POSIXt"))), 
      .Names = c("unique_visitor_id", "datetime"), 
      sorted = c("unique_visitor_id", "datetime"), 
      class = c("data.table", "data.frame"), 
      row.names = c(NA, -12L))
2个回答

8
假设您的数据框最初已按访客ID和日期时间排序,您可以在应出现新“session_id”的条件向量上使用cumsum()函数:
myDT[, session_id := cumsum(c(T, diff(unique_visitor_id) != 0 | diff(datetime)/60 > 30))][]

#    unique_visitor_id            datetime session_id
# 1:               100 2016-07-25 15:43:02          1
# 2:               100 2016-08-15 15:35:16          2
# 3:               101 2016-08-01 21:24:46          3
# 4:               101 2016-08-13 05:32:27          4
# 5:               101 2016-08-13 05:33:01          4
# 6:               101 2016-08-13 05:33:37          4
# 7:               101 2016-08-13 05:34:04          4
# 8:               101 2016-08-13 05:37:42          4
# 9:               101 2016-08-13 05:38:20          4
#10:               102 2016-09-15 17:28:00          5
#11:               102 2016-09-15 17:31:04          5
#12:               103 2016-07-18 21:19:07          6

1
并且可以轻松地添加一个阶段,当事件不在同一天时(边缘情况)会增加sID。 - Clayton Stanley
2
工作得非常出色,是的@ClaytonStanley,我添加了第三个条件来检查是否为同一天,在30分钟检查之后:| diff(date(datetime)) != 0))] - daRknight

3
同dplyr的思路类似。
library(dplyr)
library(lubridate)
myDT %>% 
    mutate(new_session = c(0, diff(datetime)) > 30*60 |
                         c(0, diff(unique_visitor_id)) != 0 ) %>%
    mutate(session_id = cumsum(new_session)) %>% print()

顺便说一下,您需要同时为新用户添加一个测试用例(这两个答案都应该涵盖此内容)。当然,您可以消除new_session列,我只是觉得它有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接