识别R中序列的开始和结束

juud5qan  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(135)

以下是一个示例数据集:

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")

我尝试分析块中的序列。我想提取一个用户行为块,其中起点是“home”,终点是“cart”。例如,对于sess_id 189,我将有两个块:主页、pg 1、pg 2、购物车和主页、pg 3、购物车。
我的想法是创建一个名为index的新列,其中1表示块的一部分,如果为0,我可以过滤掉那些不属于home to cart序列的行。
使用下面的代码,我可以标记起点和终点,但不能标记home和cart之间的Activity。

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))

我希望输出如下所示:
| 进程标识|活动|ts|索引|
| - ------|- ------|- ------|- ------|
| 一百八十九|家|二○ ○二年六月九日十二时四十五分四十秒|1个|
| 一百八十九|第1页|二○ ○二年六月九日十二时四十六分零一秒|1个|
| 一百八十九|第二页|二○ ○二年六月九日十二时四十六分三十秒|1个|
| 一百八十九|手推车|二○ ○二年六月九日十二时四十七分|1个|
| 一百八十九|第三页|二○ ○二年六月九日十二时四十七分五十秒|无|
| 一百八十九|第二页|二○ ○二年六月九日十二时四十九分五十一秒|无|
| 一百八十九|家|二○ ○二年六月九日十二时四十九分五十九秒|1个|
| 一百八十九|第三页|(英译汉)|1个|
| 一百八十九|手推车|[001 pdf 1st-31 files] 2002年6月9日13时30分|1个|
| 一百八十九|第1页|二○ ○二年六月九日十三时三十一分零二秒|无|
| 一百二十四|家|二○ ○二年六月九日十三时三十一分四十五秒|1个|
| 一百二十四|第二页|二○ ○二年六月九日十三时三十二分二十八秒|1个|
| 一百二十四|第三页|二○ ○二年六月九日十三时三十二分三十秒|1个|
| 一百二十四|手推车|二○ ○二年六月九日十三时三十二分三十二秒|1个|
| 一百二十四|第二页|二○ ○二年六月九日十三时三十三分二十八秒|无|
我也愿意听取建议和替代方案。

lnlaulya

lnlaulya1#

一种简单的基本R方法是创建seqVectorize'd函数,并使用grep来标识“from”行(包含“home”)和“to”行(包含“cart”),然后进行子集化:

seqV <- Vectorize(seq.default, 
                  vectorize.args = c("from", "to"))

keeps <- unlist(seqV(grep("home", df$Activity), 
                     grep("cart", df$Activity)))

blocks <- df[keeps, ]

这将创建一个新的数据框blocks,其中只包含所需的观测值。但是,如果您想创建一个索引变量并保留完整的数据集,您可以通过以下方式直接将其添加到df中:

df[keeps, "index"] <- 1
df[setdiff(1:nrow(df),keeps), "index"] <- 0

#    sess_id Activity                  ts index
# 1      189     home 2002-06-09 12:45:40     1
# 2      189      pg1 2002-06-09 12:46:01     1
# 3      189      pg2 2002-06-09 12:46:30     1
# 4      189     cart 2002-06-09 12:47:00     1
# 5      189      pg3 2002-06-09 12:47:50     0
# 6      189      pg2 2002-06-09 12:49:51     0
# 7      189     home 2002-06-09 12:49:59     1
# 8      189      pg3 2002-06-09 13:00:00     1
# 9      189     cart 2002-06-09 13:30:00     1
# 10     189      pg1 2002-06-09 13:31:02     0
# 11     124     home 2002-06-09 13:31:45     1
# 12     124      pg2 2002-06-09 13:32:28     1
# 13     124      pg3 2002-06-09 13:32:30     1
# 14     124     cart 2002-06-09 13:32:32     1
# 15     124      pg2 2002-06-09 13:33:28     0
sxissh06

sxissh062#

sequence的另一种方式:

w = which(df$Activity %in% c("home", "cart"))
idx = sequence(w[c(F, T)] - w[c(T, F)] + 1, w[c(T, F)])
df$index <- +(seq_len(nrow(df)) %in% idx)

输出

sess_id Activity                  ts index
1      189     home 2002-06-09 12:45:40     1
2      189      pg1 2002-06-09 12:46:01     1
3      189      pg2 2002-06-09 12:46:30     1
4      189     cart 2002-06-09 12:47:00     1
5      189      pg3 2002-06-09 12:47:50     0
6      189      pg2 2002-06-09 12:49:51     0
7      189     home 2002-06-09 12:49:59     1
8      189      pg3 2002-06-09 13:00:00     1
9      189     cart 2002-06-09 13:30:00     1
10     189      pg1 2002-06-09 13:31:02     0
11     124     home 2002-06-09 13:31:45     1
12     124      pg2 2002-06-09 13:32:28     1
13     124      pg3 2002-06-09 13:32:30     1
14     124     cart 2002-06-09 13:32:32     1
15     124      pg2 2002-06-09 13:33:28     0
watbbzwu

watbbzwu3#

使用purrr::accumulate

library(dplyr)
library(purrr)

df |>
    group_by(sess_id) |>
    mutate(block = accumulate(Activity,
                              ~if(.y == "home")
                                   1
                               else if (.y == "cart")
                                   -1
                               else if (.x < 0)
                                   0
                               else .x,
                              .init = 0) |>
               tail(-1) |>
               abs())

##>    sess_id Activity ts                  block
##>      <dbl> <chr>    <chr>               <dbl>
##>  1     189 home     2002-06-09 12:45:40     1
##>  2     189 pg1      2002-06-09 12:46:01     1
##>  3     189 pg2      2002-06-09 12:46:30     1
##>  4     189 cart     2002-06-09 12:47:00     1
##>  5     189 pg3      2002-06-09 12:47:50     0
##>  6     189 pg2      2002-06-09 12:49:51     0
##>  7     189 home     2002-06-09 12:49:59     1
##>  8     189 pg3      2002-06-09 13:00:00     1
##>  9     189 cart     2002-06-09 13:30:00     1
##> 10     189 pg1      2002-06-09 13:31:02     0
##> 11     124 home     2002-06-09 13:31:45     1
##> 12     124 pg2      2002-06-09 13:32:28     1
##> 13     124 pg3      2002-06-09 13:32:30     1
##> 14     124 cart     2002-06-09 13:32:32     1
##> 15     124 pg2      2002-06-09 13:33:28     0

相关问题