在R语言中识别用户行为序列的起止区块
提取以
home为起点、cart为终点的用户行为区块 示例数据集
df <- structure(list( sess_id = c(189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 124, 124,124,124,124), Activity = c("home", "pg1", "pg2", "cart", "pg3", "pg2", "home", "pg3", "cart","pg1","home","pg2", "pg3", "cart", "pg2"), ts = c("2002-06-09 12:45:40","2002-06-09 12:46:01","2002-06-09 12:46:30","2002-06-09 12:47:00","2002-06-09 12:47:50", "2002-06-09 12:49:51", "2002-06-09 12:49:59", "2002-06-09 13:00:00", "2002-06-09 13:30:00", "2002-06-09 13:31:02", "2002-06-09 13:31:45", "2002-06-09 13:32:28", "2002-06-09 13:32:30", "2002-06-09 13:32:32", "2002-06-09 13:33:28")), .Names = c("sess_id", "Activity", "ts"), row.names = c(NA, -15L), class = "data.frame")
需求说明
按sess_id分组,分析用户行为序列,提取每个会话中以home为起点、cart为终点的连续行为区块,给区块内的所有行标记index=1,区块外的行标记index=0。例如sess_id=189包含两个目标区块:home, pg1, pg2, cart 和 home, pg3, cart。
现有尝试的问题
以下代码仅能标记home和cart这两个起止点,无法标记两者之间的行为:
df %>% group_by(sess_id) %>% arrange(ts) %>% mutate(index = case_when(Activity == "home" | Activity == "cart" ~ 1, TRUE ~ 0)) %>% mutate(index = as.numeric(index)) %>% ungroup()%>% mutate(block_index = cumsum(index))
解决方案
可以通过标记区块的激活状态来实现:在每个会话内,当遇到home时激活标记(进入区块),遇到cart时关闭标记(退出区块),中间的行保持激活状态。代码如下:
library(dplyr) df %>% group_by(sess_id) %>% arrange(ts, .by_group = TRUE) %>% # 标记区块的激活状态:1=激活,0=未激活 mutate( # 初始化激活状态,默认0 active = 0, # 遇到home时激活 active = ifelse(Activity == "home", 1, active), # 遇到cart时关闭激活(滞后一行,因为cart本身属于区块) active = ifelse(Activity == "cart", 0, active), # 向前填充激活状态,让home到cart之间的行都保持1 active = lag(active, default = 0), # 修正cart的标记,确保属于区块 index = ifelse(Activity == "cart", 1, active), # 修正home的标记,确保属于区块 index = ifelse(Activity == "home", 1, index) ) %>% select(-active) %>% ungroup()
逻辑解释
- 按会话分组并按时间排序,确保行为序列顺序正确。
- 初始化
active列标记区块激活状态,遇到home设为1,遇到cart设为0。 - 使用
lag()向前填充激活状态,让home之后到cart之前的所有行保持激活状态(1)。 - 单独修正
cart和home的标记,确保它们本身属于目标区块。 - 最终得到
index列,1表示属于目标区块,0表示不属于。
期望输出
| sess_id | Activity | ts | index |
|---|---|---|---|
| 189 | home | 2002-06-09 12:45:40 | 1 |
| 189 | pg1 | 2002-06-09 12:46:01 | 1 |
| 189 | pg2 | 2002-06-09 12:46:30 | 1 |
| 189 | cart | 2002-06-09 12:47:00 | 1 |
| 189 | pg3 | 2002-06-09 12:47:50 | 0 |
| 189 | pg2 | 2002-06-09 12:49:51 | 0 |
| 189 | home | 2002-06-09 12:49:59 | 1 |
| 189 | pg3 | 2002-06-09 13:00:00 | 1 |
| 189 | cart | 2002-06-09 13:30:00 | 1 |
| 189 | pg1 | 2002-06-09 13:31:02 | 0 |
| 124 | home | 2002-06-09 13:31:45 | 1 |
| 124 | pg2 | 2002-06-09 13:32:28 | 1 |
| 124 | pg3 | 2002-06-09 13:32:30 | 1 |
| 124 | cart | 2002-06-09 13:32:32 | 1 |
| 124 | pg2 | 2002-06-09 13:33:28 | 0 |
内容的提问来源于stack exchange,提问作者user2845095
相关产品推荐
相关产品推荐

