这是我的问题。我有一个大的正数据向量。我的目标是删除在向量中重复的至少N个连续值的序列(所有重复值必须严格地> 0)。
我写了一个有效的程序,如下: X是我的数值向量; N是重复序列的最小长度。
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)
}
我认为我的功能真的不是最优的(对于92,000个值的矢量计算时间为1:15,N = 18)。我必须做1600次这个步骤......这需要大约3个月......
有没有人有更好的主意?
示例:
x <- c(1,2,3,4,0,4,1,2,3,8,9,1,2,3,4,0)
N <- 3
# (1,2,3) is a sequence of 3 elements which is repeated
# (1,2,3,4) is sequence of 4 elements which is repeated
# no other sequence of length at least 3 repeats
# my result should also be :
# NA NA NA NA 0 4 NA NA NA 8 9 NA NA NA NA 0
# The result of my program is :
# $X
# [1] NA NA NA NA 0 4 NA NA NA 8 9 NA NA NA NA 0
#$Ind.sup
# [1] 1 2 3 4 7 8 9 12 13 14 15
答案 0 :(得分:1)
尝试使用table
和%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
对92000值进行一点测试:
X<-sample(1:10000,92000,TRUE)
system.time(rmpParNASerieRepetee(X,3))
# user system elapsed
# 0.14 0.00 0.14
答案 1 :(得分:1)
一种方式:
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
答案 2 :(得分:0)
考虑这一点的一种方法是,在一个序列中,每个元素与最后一个元素的区别为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
现在你正在寻找&gt;的序列。 {1}中的N 1。
答案 3 :(得分:0)
我已经优化了我的功能,现在对于长度为92000的向量,“仅”10分钟。 也许有人能找到比我更快的其他解决方案。
想象一下,我的矢量是X<-c(1,2,3,4,0,7,8,1,2,3,NA,8,9,1,2,3,4)
和N=3
。
c(1,2,3)
et c(1,2,3,4)
是唯一一个长度至少为N而没有NA或0的重复序列。所以我的结果应该是NA NA NA NA 0 7 8 NA NA NA NA 8 9 NA NA NA NA
。
为了回答我的问题,我使用了这个原则:
我创建了一个大字符串:X_ <- T1T2T3T4T0T7T8T1T2T3TNAT8T9T1T2T3T4
,其中所有X
值都由T
连接。对于每个长度为N=3
的小字符串(例如:第一个是T1T2T3T
),我使用X_
函数以“小字符串”模式打破我的大字符串strsplit
。如果结果的长度大于2,则重复该序列。
必须注意不要在系列中取空值,并且必须进行一些调整以避免边缘现象(在我的函数中borne
)......
我创建了这些功能:
# 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)
}
我希望有人能找到另一种方法来解决我的问题!