我有一个向量,里面有重复的模式。我想要在n长度的重复模式改变的任何地方中断。以下是数据:
x <- c(rep(1:4, 5), rep(5:6, 3), rep(c(1, 4, 7), 5), rep(c(1, 5, 7), 1), rep(2:4, 3))
## [1] 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 5 6 5 6 1 4 7 1 4 7 1 4 7 1 4 7 1 4 7 1 5 7 2 3 4 2 3 4 2 3 4
我希望能够找到那些模式改变的地方,这样它就会像这样崩溃:
我认为rle
可能会有用处,但不知道如何使用。
发布于 2015-10-16 10:40:15
这里有一个函数可以做到这一点。顺便说一下,这是遗传学上的一个问题--寻找串联重复序列。Here's a link to an algorithm paper是一种比这更好的处理方法,但实现起来要复杂得多。
输出是要将x拆分成的组的向量。
首先是一个辅助函数:
factorise <- function(x) {
x <- length(x)
if(x == 1){return(1)}
todivide <- seq(from = 2, to = x)
out <- todivide[x %% todivide == 0L]
return(out)
}
现在主要的功能是:
findreps <- function(x, counter = NULL){
if(is.null(counter)){
counter <- c()
maxcounter <- 0
} else {
maxcounter <- max(counter)
}
holding <- lapply(1:length(x), function(y){x[1:y]})
factors <- lapply(holding, factorise)
repeats <- sapply(1:length(factors), function(index) {any(sapply(1:length(factors[[index]]), function(zz) {all((rep(holding[[index]][1:(length(holding[[index]])/factors[[index]][zz])], factors[[index]][zz]))==holding[[index]])}))})
holding <- holding[max(which(repeats))][[1]]
if(length(holding) == length(x)){
return(c(counter, rep(maxcounter + 1, length(x))))
} else {
counter <- c(counter, rep(maxcounter + 1, length(holding)))
return(findreps(x[(length(holding) + 1):length(x)], counter))
}
}
它的工作原理:它是一个递归函数,它运行,切断它能找到的从向量开始的最大重复组,然后运行,直到它们都消失。
首先,我们为最终输出创建一个counter
。
接下来,我们将从1开始将x
划分为每个子集,并将其划分为一个列表holding
。
然后我们找出一个组大小的所有因素,除了1。
然后才是最糟糕的部分。我们取最大子集的每个子集,并在重复合理的次数后检查它是否等于其组中的最大子集。
findreps(x)
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
[37] 3 3 3 3 3 4 5 6 7 7 7 7 7 7 7 7 7
如果您希望对非重复序列进行分组,我们可以使用一些dplyr
和tidyr
library(dplyr)
library(tidyr)
z <- data.frame(x = x, y = findreps(x))
z %>% mutate(y = ifelse(duplicated(y) | rev(duplicated(rev(y))), y, NA),
holding = c(0, y[2:n()])) %>%
fill(holding) %>%
mutate(y = ifelse(is.na(y), holding +1, y)) %>%
select(-holding)
这就给出了:
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 7 7 7 7 7 7 7 7
[53] 7
发布于 2015-10-16 03:46:38
我就快到了,但是我没有完成全部工作,而且已经很晚了(zzz)。首先是代码:
x <-c(rep(1:4, 5), rep(5:6, 3), rep(c(1, 4, 7), 5), rep(c(1, 5, 7), 1), rep(2:4, 3))
#The first break must be position 1
Xbreaklist <- 1
#We need a counter, a duplicate dataset
counter <- 0
xx <- x
while (length(xx) > 0) {
#first we extract a pattern by looking for the first repeated number
Xpattern <- xx[1:(min(which(stri_duplicated(xx) == TRUE))-1)]
#then we convert the vector and the pattern into a string
XpatternS <- paste0(Xpattern, collapse="")
xxS <- paste0(xx, collapse="")
#then we extract all patterns and count them, multiply by length and add 1
Xbreak <- 1 + (length(unlist(stri_extract_all_coll(xxS, XpatternS))) * length(Xpattern))
#break here if we reached the end
if (Xbreak >= length(xx)) break
# We add that to the list of breaks
counter <- counter + Xbreak
Xbreaklist <- c(Xbreaklist, counter)
# then we remove the part of the list we're done with
xx <- xx[(Xbreak):length(xx)]
}
Xbreaklist
[1] 1 21 28 44 51
它有什么问题?两件事:
1不重复的模式将第一次出现的下一个模式:"121212 56 787878“被拆分为("121212 567878”)
2个重复的模式(“1212565612134”)把事情搞乱了,因为stri_extract_all_coll
把它们都去掉了,因此长度太长了。
发布于 2015-10-16 07:45:16
这是一个部分的答案,但我认为这比在评论中发布要好。这可能会让其他人找到一种方法来做到这一点。
我的想法是将向量分成大小为N的相等部分,然后检查连续的块是否是前一个块的副本。我这样做的方式可能太长了--我相信肯定有更简单的方式来做。
它似乎工作得很好,可以形成另一种方式的基础。缺点是它不能识别只出现一次的重复序列,例如"157“。
xx <- split(x, ceiling(seq_along(x)/N)) #split vector into equal chunks of size N
xx <- xx[-(length(xx))] #get rid of uneven splitting of last vector
df <- do.call('rbind', xx) #bind together in a dataframe
results<-NULL #loop to test if row is same as previous row (must be better way to do this)
for(i in 2:nrow(df)-1) {results[[i]] <- df[i,]==df[i+1,] }
results1 <- unlist(lapply(results, sum)) #count TRUEs in each result
results1[results1<N]<-0 #make all not equal to size of chunk (N) equal to zero
indices <- which(diff(results1)==-N)+1 #this is the first non-repeating group of N
indicesall <- (indices*N)+1 #to find location of next non-repeating id
https://stackoverflow.com/questions/33155662
复制相似问题