检测两个序列之间的差异

时间:2018-10-29 11:26:07

标签: r

我有两个时间序列向量:complete_dataincomplete_data。向量中的数据包含6个可能的事件,这些事件在整个向量中随机发生。原则上,这两个应该是相同的,因为对于complete_data中的每个事件,都将同一事件添加到incomplete_data上。但是实际上,系统中存在一些异常,并非complete_data中的所有事件都被发送到incomplete_data。因此complete_dataincomplete_data长。我需要找到两者之间的模式差异并将其标记出来。我进行了尝试,但假设两个向量之间的差异发生在单个块中,而实际上,incomplete_data中散布着各种“缺失事件”。

这是我的尝试:

complete_data <- c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')
dfcomplete <- as.data.frame(complete_data)
incomplete_data <- c('a', 'b', 'c', 'a','c', 'a', 'b', 'a', 'b', 'c')
dfincomplete <- as.data.frame(incomplete_data)

findMatch <- function(complete_data, incomplete_data){

  matching_inorder <- NULL
  matching_reverseorder <- NULL

  for (i in 1:length(complete_data)){
    matching_inorder[i] <- complete_data[i] == incomplete_data[i]
    matching_reverseorder[i] <- rev(complete_data)[i] == rev(incomplete_data)[i]
  }

  is_match <- ifelse(matching_inorder == FALSE & 
                       rev(matching_reverseorder) == FALSE, 'non_match', 'match')
  is_match
}

dfcomplete$is_match_incorrect <- findMatch(dfcomplete$complete_data,
                                 dfincomplete$incomplete_data)

这就是我想要得到的:

dfcomplete$expected_output <- c('match', 'match', 'match', 'match', 'non-match', 'match',
                 'match', 'match', 'non_match', 'match', 'match', 'match')

实际上,我的数据比这些示例要大得多,在整个向量中散布了许多不同的差异。尽管不一定有太多差异可以使任务变得毫无意义,例如,在一种情况下,complete向量具有320个数据点,而incomplete向量具有309个数据点。

我们将不胜感激。

2 个答案:

答案 0 :(得分:3)

执行此操作的方法有很多种,但这是一种递归方法,其中x被假定为完整序列,而y被认为是不完整序列。

compare <- function(x, y) {
  if (length(x) > 0) {
    if (x[1] == y[1]) {
      x[1] <- "match"
      c(x[1], compare(x[-1], y[-1]))
    } else {
      x[1] <- "no match"
      c(x[1], compare(x[-1], y))
    }
  }
}
compare(complete_data, incomplete_data)
# [1] "match"    "match"    "match"    "match"    "no match" "match"   
# [7] "match"    "match"    "no match" "match"    "match"    "match" 

另一种可能更易读并且使用简单循环的方法是

out <- rep(NA, length(incomplete_data))
gap <- 0
for(i in seq_along(complete_data)) {
  if (complete_data[i] == incomplete_data[i - gap]) {
    out[i] <- "match"
  } else {
    out[i] <- "no match"
    gap <- gap + 1
  }
}
out
# [1] "match"    "match"    "match"    "match"    "no match" "match"   
# [7] "match"    "match"    "no match" "match"    "match"    "match" 

答案 1 :(得分:1)

如果负担不起只有一个字母长的事件名称,那么这是使用字符串匹配的解决方案。诀窍是将不完整的数据转换为包含插入新字符的位置的模式。

complete_data <- c('a', 'b', 'c', 'a', 'B', 'c', 'a', 'b', 'C', 'a', 'b', 'c')
dfcomplete <- as.data.frame(complete_data,stringsAsFactors=FALSE)
incomplete_data <- c('a', 'b', 'c', 'a','c', 'a', 'b', 'a', 'b', 'c')

y <- paste0('^(.*)',paste(incomplete_data,collapse='(.*)'),'(.*)$')
x <- paste(complete_data,collapse="")
z <- str_length(str_match(x,y)[-1])

data.frame(incomplete_data=c("",incomplete_data),stringsAsFactors=FALSE) %>%
  mutate(n=ifelse(incomplete_data=="",z,z+1)) %>%
  filter(n>0) %>%
  uncount(n) %>%
  mutate(incomplete_data=ifelse(str_detect(rownames(.),"\\."),"",incomplete_data)) %>%
  bind_cols(dfcomplete) %>%
  mutate(match=complete_data==incomplete_data)
#   incomplete_data complete_data match
#1                a             a  TRUE
#2                b             b  TRUE
#3                c             c  TRUE
#4                a             a  TRUE
#5                              B FALSE
#6                c             c  TRUE
#7                a             a  TRUE
#8                b             b  TRUE
#9                              C FALSE
#10               a             a  TRUE
#11               b             b  TRUE
#12               c             c  TRUE