R 删除向量中至少N个连续值的序列
这是我的问题。我有大量的正面数据。我的目标是删除至少N个连续值的序列在向量中重复的(所有重复值必须严格大于0) 我已经编写了一个程序,如下所示: X是我的数值向量; N是重复序列的最小长度R 删除向量中至少N个连续值的序列,r,optimization,vector,R,Optimization,Vector,这是我的问题。我有大量的正面数据。我的目标是删除至少N个连续值的序列在向量中重复的(所有重复值必须严格大于0) 我已经编写了一个程序,如下所示: X是我的数值向量; N是重复序列的最小长度 rmpParNASerieRepetee <- function(X, N) { X_ <- paste("T", paste(X, collapse="T"), "T", sep="") ind.parcours <- 1 ind.sup <- c()
rmpParNASerieRepetee <- function(X, N)
{
X_ <- paste("T", paste(X, collapse="T"), "T", sep="")
ind.parcours <- 1
ind.sup <- c()
# Loop on the values
while ( ind.parcours <= (length(X)-N+1) )
{
# indices of my sequence of N values
deb <- ind.parcours
fin <- ind.parcours + N-1
# sequence of N values to search in the vector
serie <- X[deb:fin]
serie_ <- paste("T", paste(serie, collapse="T"), "T", sep="")
borne <- 1*(ind.parcours < (length(X)-N+1)) + 0*(ind.parcours == (length(X)-N+1))
if (sum(X[(length(X)-N+1):length(X)]==serie)==3) borne <- 0
# split my string vector by my sequence vector of N values and count the pieces of result
if ( length(unlist(strsplit(X_, serie_)))-1 > borne && length(which(serie!=0))>=N)
{ ind.sup <- unique(c(ind.sup, deb:fin)) }
ind.parcours <- ind.parcours+1
}
if (length(ind.sup !=0)) { X[ind.sup] <- NA }
list_return <- list(X=X, Ind.sup=unique(sort(ind.sup)))
return (list_return)
}
rmpparnaserieretee考虑这一点的一种方法是,在一个序列中,每个元素与最后一个元素相差1,因此:
X <- c(1,2,3,4,0,0,0,0,1,4,1,2,3,4,8,9,1,2,3,1,4,1,0,0,0)
y <- X[-1]
diff <- y-X[1:length(X)-1]
diff
[1] 1 1 1 -4 0 0 0 1 3 -3 1 1 1 4 1 -8 1 1 -2 3 -3 -1 0 0
X尝试使用表格
和%
中的%in%
来获得更快的速度,因为矢量化
rmpParNASerieRepetee<-function(X,N){
tab<-table(X[X>0])
over.n<-as.numeric(names(tab)[tab>=N])
ind<-X %in% over.n
Ind.sup<-which(ind)
X<-ifelse(ind,NA,X)
list(Ind.sup,X)
}
X <- c(1,2,3,4,0,0,0,0,1,4,1,2,3,4,8,9,1,2,3,1,4,1,0,0,0)
rmpParNASerieRepetee(X,3)
# [[1]]
# [1] 1 2 3 4 9 10 11 12 13 14 17 18 19 20 21 22
#
# [[2]]
# [1] NA NA NA NA 0 0 0 0 NA NA NA NA NA NA 8 9 NA NA NA NA NA NA 0 0 0
rmpparanserierepeteA方法:
f我已经优化了我的函数,现在对于长度为92000的向量,“只”需要10分钟。
也许有人能找到比我更快的解决方案
假设我的向量是x为什么不描述一下你要做的事情,它比放代码有用得多。你的数据看起来像整数。如果是这种情况,按原样存储(integer
而不是numeric
)可以使建议的答案更快。问题:单个元素可以有多大?它们都在(0,9)中吗?不,我不知道这些值。它可以是2作为1256。我添加了一个例子,你能看到我的新编辑吗?谢谢+1,但您真的应该在代码中留出一些空间。例如Ind可能使用over.n=n)
和X[Ind.sup]我的序列是由n个连续的值组成的。事实是:让X@sandikou抱歉,我想我误解了你的问题。我的误解恰好有相同的结果,这使我相信我理解正确。我的重复序列可能是c(1,4,1)
,在这种情况下,diff
函数不能帮助记忆序列由N个连续值组成c(1,4,1,4,1,4,1,4,1,4)
在大多数人对这个词的理解中不是“连续的”。这是一个循环长度为2的重复序列。我的序列由N个连续序列组成values@sandikou,它们返回的输出与您在问题中显示的相同。所以,如果这不是你想要的,你需要更清楚一点并编辑你的问题。这是不够的。请提供一个例子,说明您对连续性的定义与此相关。同样,这里的答案给出的输出与您的相同…@sandikou:您能否添加一个示例,说明您的函数与此处发布的函数之间的输出不同?一、 老实说,我不能得到它。这也给出了一个与OP的代码x不同的结果
rmpParNASerieRepetee<-function(X,N){
tab<-table(X[X>0])
over.n<-as.numeric(names(tab)[tab>=N])
ind<-X %in% over.n
Ind.sup<-which(ind)
X<-ifelse(ind,NA,X)
list(Ind.sup,X)
}
X <- c(1,2,3,4,0,0,0,0,1,4,1,2,3,4,8,9,1,2,3,1,4,1,0,0,0)
rmpParNASerieRepetee(X,3)
# [[1]]
# [1] 1 2 3 4 9 10 11 12 13 14 17 18 19 20 21 22
#
# [[2]]
# [1] NA NA NA NA 0 0 0 0 NA NA NA NA NA NA 8 9 NA NA NA NA NA NA 0 0 0
X<-sample(1:10000,92000,TRUE)
system.time(rmpParNASerieRepetee(X,3))
# user system elapsed
# 0.14 0.00 0.14
f <- function(X, N)
{
.rle <- rle(sort(X))
res <- .rle$values[.rle$lengths >= N]
res <- res[res > 0]
inds <- X %in% res
X[inds] <- NA
list(X = X, Ind = which(inds))
}
#> f(X, 3)
#$X
# [1] NA NA NA NA 0 0 0 0 NA NA NA NA NA NA 8 9 NA NA NA NA NA NA 0 0 0
#
#$Ind
# [1] 1 2 3 4 9 10 11 12 13 14 17 18 19 20 21 22
# Function to count NA in a vector
count.na <- function(vec) { return (length(which(is.na(vec)))) }
# Function to detect sequence of stricly postive numbers of length at least N
rmpParNASerieRepetee <- function(X, N, val.min=0)
{
# Collapse the vector to make a big string
X_ <- paste("T", paste(X, collapse="T"), "T", sep="")
# Index term
ind.parcours <- 1
ind.sup <- c()
# Loop on X values
while ( ind.parcours <= (length(X)-N+1) )
{
# Selection of the sequence to be detected
deb <- ind.parcours
fin <- ind.parcours + N-1
serie <- X[deb:fin]
# All values are > 0
if ( length(which(serie>0)) >= (N-count.na(serie)) )
{
# Research of repetition with strsplit
serie_ <- paste("T", paste(serie, collapse="T"), "T", sep="")
borne <- 1*(ind.parcours < (length(X)-N+1)) + 0*(ind.parcours == (length(X)-N+1))
if (sum(X[(length(X)-N+1):length(X)]==serie, na.rm=TRUE)==N) borne <- 0
if (length(unlist(strsplit(X_, serie_)))-1 > borne)
ind.sup <- unique( c(ind.sup, deb:fin) )
# Incrementation
ind.parcours <- ind.parcours + 1
}
# Contains 0
else
{ ind.parcours <- ind.parcours + max(which(serie==0))
}
}
# Invalidaion of repeated sequences
if (length(ind.sup !=0)) { X[ind.sup] <- NA }
# Return
list_return <- list(X=X, Ind.sup=unique(sort(ind.sup)))
return (list_return)
}