4

是否可以计算 R 中序列的重复部分?例如:

x<- c(1,3.0,3.1,3.2,1,1,2,3.0,3.1,3.2,4,4,5,6,5,3.0,3.1,3.2,
      3.1,2,1,4,6,4.0,4,3.0,3.1,3.2,5,3.2,3.0,4)

是否可以计算子序列 3.0,3.1,3.2 出现的次数?所以在这个例子中它必须是:4

4

4 回答 4

5

我会做这样的事情:

pattern <- c(3, 3.1, 3.2)
len1 <- seq_len(length(x) - length(pattern) + 1)
len2 <- seq_len(length(pattern))-1
sum(colSums(matrix(x[outer(len1, len2, '+')], 
     ncol=length(len1), byrow=TRUE) == pattern) == length(len2))

PS:通过更改sumwhich您将获得每个实例的开始。

于 2013-06-28T13:58:03.867 回答
3

另一种(通用移动窗口)方法:

x <- c(1,3.0,3.1,3.2,1,1,2,3.0,3.1,3.2,4,4,5,6,5,3.0,3.1,3.2, 3.1,2,1,4,6,4.0,4,3.0,3.1,3.2,5,3.2,3.0,4)
s <- c(3, 3.1, 3.2)

sum(apply(embed(x, length(s)), 1, function(y) {all(y == rev(s))}))
# [1] 4

查看输出embed以了解正在发生的事情。

正如 Arun 指出的那样,apply这里的速度非常慢,可以embed与 Arun 的matrix技巧一起使用以使其更快:

sum(colSums(matrix(embed(x, length(s)),
                   byrow = TRUE, nrow = length(s)) == rev(s)) == length(s))
于 2013-06-28T15:08:16.947 回答
2

Carl Witthoft 的seqle功能在这里可能对您有用。

该函数如下所示:

seqle <- function(x,incr=1) { 
    if(!is.numeric(x)) x <- as.numeric(x) 
    n <- length(x)  
    y <- x[-1L] != x[-n] + incr 
    i <- c(which(y|is.na(y)),n) 
    list(lengths = diff(c(0L,i)),
         values = x[head(c(0L,i)+1L,-1L)]) 
}

应用于您的数据,它应该如下所示:

temp <- seqle(x, incr=.1)
temp
# $lengths
#  [1] 1 3 1 1 1 3 1 1 1 1 1 3 1 1 1 1 1 1 1 3 1 1 1 1
# 
# $values
#  [1] 1.0 3.0 1.0 1.0 2.0 3.0 4.0 4.0 5.0 6.0 5.0 3.0 3.1 2.0 1.0 4.0
# [17] 6.0 4.0 4.0 3.0 5.0 3.2 3.0 4.0

现在,我们如何阅读它?lengths告诉我们我们的向量有一个序列 1,然后是 3,然后是 1,然后是 1,和 1,和 3....values告诉我们长度为 3 的序列的第一个值是“3.0” ,下一个长度为 3 的序列的第一个值为“3.0”,依此类推。

这更容易被视为data.frame.

data.frame(temp)[temp$lengths > 1, ]
#    lengths values
# 2        3      3
# 6        3      3
# 12       3      3
# 20       3      3

在这个例子中,所有序列的长度都是相同的,并且它们从相同的值开始,所以我们只需查看上面结果中的行数就可以得到答案data.frame

于 2013-06-28T14:34:23.423 回答
2

你可以把它变成一个字符串,然后使用gregexpr.

sum(gregexpr("3 3.1 3.2", paste(x, collapse=" "), fixed=TRUE)[[1]] != -1)
[1]  4
于 2013-06-28T13:50:16.853 回答