是否可以计算 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
我会做这样的事情:
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:通过更改sum
为which
您将获得每个实例的开始。
另一种(通用移动窗口)方法:
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))
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
。
你可以把它变成一个字符串,然后使用gregexpr
.
sum(gregexpr("3 3.1 3.2", paste(x, collapse=" "), fixed=TRUE)[[1]] != -1)
[1] 4