发现所有频繁序列的集合

时间:2017-08-17 13:13:59

标签: python r

我需要找到发生的所有频繁事件序列的集合。 数据由两列组成,即带有时间戳的日期和事件。 我需要帮助来找出用于检查用户行为的频繁事件集。 以下是样本数据

    date     events
6/1/17 7:25     A
6/1/17 7:33     B
6/1/17 7:33     C
6/1/17 7:33     D
6/1/17 7:33     Z
6/1/17 7:33     C
6/1/17 7:33     G
6/1/17 7:34     H
6/1/17 7:34     J
6/1/17 7:34     K
6/1/17 7:34     A
6/1/17 7:34     B
6/1/17 7:34     C
6/1/17 7:34     D
6/1/17 7:34     F
6/1/17 7:35     G
6/1/17 7:35     J
6/1/17 7:35     Y
6/1/17 7:35     D
6/1/17 7:35     A
6/1/17 7:35     B
6/1/17 7:35     C
6/1/17 7:35     D

正如您在数据中看到的那样,事件' ABCD'是最常见的序列。我需要一个输出说'ABCD'事件发生了3次。 任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

注意A,B,AB,BC,CD,ABC和BCD的发生频率与ABCD一样频繁,C和D各自更频繁地发生,因此我们将重新解释问题,因为找到每个序列长度k> 1(最多9)最常出现的序列。低于Lall[[i]]给出所有长度为i + 1的序列,以下行将其减少为具有该序列长度的最大频率的那些序列。在下面我们将其减少到那些不是列表中其他序列的子序列的序列。

library(zoo)

k <- 2:9
Lall <- setNames(lapply(k, function(i) table(rollapply(event, width = i, toString))), k)
L <- Filter(length, lapply(Lall, function(x) x[x == max(x) & x > 1]))

,并提供:

$`2`

A, B B, C C, D 
   3    3    3 

$`3`

A, B, C B, C, D 
      3       3 

$`4`
A, B, C, D 
         3 

我们可以选择性地将其进一步减少到那些不是另一个序列的子序列的序列,除非它们具有更高的频率:

vec <- unlist(unname(L))
nms <- names(vec)
is_le <- function(i) any(grepl(nms[i], tail(nms, -i)) & (vec[i] <= tail(vec, -i)))
vec[ ! sapply(seq_along(nms), is_le) ]

,并提供:

A, B, C, D 
         3 

注意:我们使用了这个输入:

Lines <- "date     events
6/1/17 7:25     A
6/1/17 7:33     B
6/1/17 7:33     C
6/1/17 7:33     D
6/1/17 7:33     Z
6/1/17 7:33     C
6/1/17 7:33     G
6/1/17 7:34     H
6/1/17 7:34     J
6/1/17 7:34     K
6/1/17 7:34     A
6/1/17 7:34     B
6/1/17 7:34     C
6/1/17 7:34     D
6/1/17 7:34     F
6/1/17 7:35     G
6/1/17 7:35     J
6/1/17 7:35     Y
6/1/17 7:35     D
6/1/17 7:35     A
6/1/17 7:35     B
6/1/17 7:35     C
6/1/17 7:35     D"

DF <- read.table(text = Lines, skip = 1, as.is = TRUE, 
    col.names = c("Date", "Time", "event"))
event <- DF$event

更新:显示如何将L减少到那些不是L中其他序列的子序列的序列,除非它们具有更高的频率。

答案 1 :(得分:2)

我们可以创建一个函数来根据bin长度创建所有字母组合。之后,使用table计算数字并返回具有最大计数的单词。这种方法的优点是用户可以更改bin长度,例如3或2,取决于他们的目标。

# Create the vector
events <- c("A", "B", "C", "D", "Z", "C", "G", "H", 
            "J", "K", "A", "B", "C", "D", "F", "G",
            "J", "Y", "D", "A", "B", "C", "D")


# Design a function to group letters based on a bin size
bin_fun <- function(vec, bin){
  iter <- length(events) - bin + 1
  result <- character()
  for (i in 1:iter){
   vec2 <- vec[i:(i + bin - 1)]
   word <- paste(vec2, collapse = "")
   result <- c(result, word)
  }
  return(result)
}

# Apply the bin_fun to events and bin = 4
result <- bin_fun(events, 4)

# Count number of each word
table(result)
result
ABCD BCDF BCDZ CDFG CDZC CGHJ DABC DFGJ DZCG FGJY GHJK GJYD HJKA JKAB JYDA KABC YDAB ZCGH 
   3    1    1    1    1    1    1    1    1    1    1    1    1    1    1    1    1    1

# Return the word with maximum count
table(result)[which.max(table(result))]
ABCD 
   3

答案 2 :(得分:1)

您的数据

df <- structure(list(date = c("6/1/17 7:25", "6/1/17 7:33", "6/1/17 7:33", 
"6/1/17 7:33", "6/1/17 7:33", "6/1/17 7:33", "6/1/17 7:33", "6/1/17 7:34", 
"6/1/17 7:34", "6/1/17 7:34", "6/1/17 7:34", "6/1/17 7:34", "6/1/17 7:34", 
"6/1/17 7:34", "6/1/17 7:34", "6/1/17 7:35", "6/1/17 7:35", "6/1/17 7:35", 
"6/1/17 7:35", "6/1/17 7:35", "6/1/17 7:35", "6/1/17 7:35", "6/1/17 7:35"
), events = c("A", "B", "C", "D", "Z", "C", "G", "H", "J", "K", 
"A", "B", "C", "D", "F", "G", "J", "Y", "D", "A", "B", "C", "D"
)), .Names = c("date", "events"), row.names = c(NA, -23L), class = 
c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x0000000014320788>)

解决方案

将所有 N -mers( N = 1:nrow(df))保存到列表L中,然后将Reduce列表保存到向量并使用table计算每个 N -mer的出现次数,然后使用最大值保存表条目。

L <- lapply(nrow(df):1, function(x) sapply(1:(nrow(df)-(x-1)), function(y) paste0(df$events[y:(y+(x-1))], collapse="")))
T <- table(Reduce(c, L))
M <- T[T==max(T)]

输出

C D 
4 4

N-mers&gt; 1

如果您只想保存 N -mers&gt; 1,然后丢弃长度为1的 N - ,并按降序nchar

对表格进行排序
cM <- T[T==max(T[nchar(names(T))>1])]
val <- cM[sort(nchar(names(cM)), decreasing=TRUE)]

替代输出

ABCD  ABC  ABC   AB   AB   AB    A    A 
   3    3    3    3    3    3    3    3

您可以使用

保存顶部条目
head(val,1)
# ABCD
#    3

或有关系

val[nchar(names(val))==max(nchar(names(val)))]
# ABCD
#    3

答案 3 :(得分:0)

我将您的数据放入csv。

搜索最常出现的序列(我用过R):

    data = read.table(file = "path/to/csv", header = T, sep = ";")
    data$events = as.character(data$events)
    finalSequences = NULL
    for(i in 1:nrow(data)) {
      if(any(is.na(data[i:(i+3),2]))){
        stop()
      }
      sequence = paste(data[i:(i+3),2], collapse = "")
      finalSequences = c(finalSequences, sequence)
    }
    table(finalSequences)

<强>被修改

我编辑我的答案只是为了满足OP的要求。需要明确的是,它与@ycw已经指出的几乎相同。