2015-10-05 119 views
-2

从矢量开始,我想删除元素,以便其余元素不断增加。 我已经有一个反复的办法,去如下:(2,4,7,8-)创建增量矢量

test<- c(2,4,7,2,3,6,8) 
while(!all(diff(test)>=0)){ 
    rm <- which(diff(test)<0)[1]+1 
    if(!is.na(rm)) test<-test[-rm] 
} 

在我的例子预期产出将是。

有没有更聪明的方法来做到这一点?

编辑:添加算法的预期输出。

编辑:输出错字。

编辑:更正了我的代码,以便它给出所需的结果。

编辑:将示例更改为更通用的示例,在末尾添加8。

+0

你说的问题是欠定的。可能是(2,4,7),可能是(2,3,6)等等。 – tonytonov

+0

你想要的输出是什么?我会想'c(2,4,7)',但是你的代码暗示着不同的东西。而且,如果我测试< - c(2,4,7,2,3,6,9)',我不清楚你想要什么。 – ulfelder

+1

代码输出的是'c(2,2,3,6)' – Cath

回答

0

我想感谢大家对本次讨论做出的贡献我已经使用digEmAll的代码进行基准测试,并比较了以上所有方法。结果如下。

makeIncreasing_digEmAll <- function(test){ 
     test2 <- rep(NA,length(test)) 
     test2[1] <- test[1] 
     prev <- test[1] 
     for(i in 2:length(test)){ 
       if(prev < test[i]){ 
         test2[i] <- test[i] 
         prev <- test[i] 
       } 
     } 
     test2 <- test2[!is.na(test2)] 
     return(test2) 
} 

makeIncreasing_Jcl <- function(test){ 
     while(!all(diff(test)>=0)){ 
       rm <- which(diff(test)<0)[1]+1 
       if(!is.na(rm)) test<-test[-rm] 
     } 
     return(test) 
} 

makeIncreasing_Jcl2 <- function(test){ 

     return(unique(cumsum(test))) 
} 

makeIncreasing_CathG <- function(test){ 
     last_val <- test[1] 
     out_ind <- c(1) 
     i <- 2 
     while (i<=length(test)){ 
       if (test[i] >= last_val) {out_ind <- c(out_ind, i); last_val <- test[i]} 
       i <- i+1 
     } 
     return(test) 
} 

set.seed(123) 
test2 <- runif(n=1000,min=1,max=10000) 

timeDigEmAll <- system.time(for(i in 1:200)makeIncreasing_digEmAll(test2),gcFirst=T) 
timeJcl <- system.time(for(i in 1:200)makeIncreasing_Jcl(test2),gcFirst=T) 
timeJcl2 <- system.time(for(i in 1:200)makeIncreasing_Jcl2(test2),gcFirst=T) 
timeCathG <- system.time(for(i in 1:200)makeIncreasing_CathG(test2),gcFirst=T) 



> timeDigEmAll 
    user system elapsed 
    0.068 0.000 0.068 
> timeJcl 
    user system elapsed 
    14.64 0.00 14.64 
> timeJcl2 
    user system elapsed 
    0.008 0.000 0.008 
> timeCathG 
    user system elapsed 
    0.124 0.000 0.124 

总之,unique(cumsum(test))是要走的路。

4

也许这会有所帮助:

test[1:which(diff(test) < 0)] 
#[1] 2 4 7 
+2

这会失败:'test < - c(2,4,7,2,3,1)' – digEmAll

+3

尽管这会给出与他的代码不同的答案。他将删除第一个不增加的元素,然后再次返回列表,删除下一​​个不增加的元素,直到列表严格增加。当涉及到第一个不增加的元素时,此方法将切割列表。所以他的方法会给2,4,6,你会给2,4,7。 – JCollerton

+0

我很抱歉,我承认我的问题可能没有足够清楚。我的目标是去除元素,以便增加矢量。 – Jonkie

5

考虑到与你的代码获得的输出,我相信你想删除,让你的向量的数量不增加值。

EDIT2

如果你想保留的所有增加值,这里是while一个选项:

last_val <- test[1] 
out_ind <- c(1) 
i <- 2 
while (i<=length(test)){ 
    if (test[i] >= last_val) {out_ind <- c(out_ind, i); last_val <- test[i]} 
    i <- i+1 
} 

EDIT1

如果你只是想后删除号码首先不增加一个,你可以用@RHertel回答或test[1:which(diff(test) < 0)[1]]来避免警告消息,如果有多个es为负值“差异”值。

从您的代码

这里预期输出的第一个答案是一个办法做到这一点:

# get the indexes of the sorted vector 
ot <- order(test) 
# then you remove the value that doesn't correspond to increasing indexes 
test <- test[-ot[which(diff(ot)<0)+1]] 
>test 
#[1] 2 2 3 6 
+1

请能那个低调赞成争论的人呢?我得到OP代码给出的输出和(imo)我的代码正在做什么被问到 – Cath

+0

@Jcl这似乎是根据你的描述给你的循环输出。 – LyzandeR

+0

我在最初的问题中发现了一个错字,我很抱歉。 – Jonkie

1

我会用好老for-loop

test <- c(2,4,7,2,3,9) 

test2 <- rep(NA,length(test)) 
test2[1] <- test[1] 
prev <- test[1] 
for(i in 2:length(test)){ 
    if(prev < test[i]){ 
    test2[i] <- test[i] 
    prev <- test[i] 
    } 
} 
test2 <- test2[!is.na(test2)] 

#> test2 
#[1] 2 4 7 9 

基准测试:

makeIncreasing_digEmAll <- function(test){ 
    test2 <- rep(NA,length(test)) 
    test2[1] <- test[1] 
    prev <- test[1] 
    for(i in 2:length(test)){ 
    if(prev < test[i]){ 
     test2[i] <- test[i] 
     prev <- test[i] 
    } 
    } 
    test2 <- test2[!is.na(test2)] 
    return(test2) 
} 

makeIncreasing_Jcl <- function(test){ 
    while(!all(diff(test)>=0)){ 
    rm <- which(diff(test)<0)[1]+1 
    if(!is.na(rm)) test<-test[-rm] 
    } 
    return(test) 
} 


set.seed(123) 
test2 <- runif(n=1000,min=1,max=10000) 

timeDigEmAll <- system.time(for(i in 1:200)makeIncreasing_digEmAll(test2),gcFirst=T) 
timeJcl <- system.time(for(i in 1:200)makeIncreasing_Jcl(test2),gcFirst=T) 

> timeDigEmAll 
    user system elapsed 
    0.17 0.00 0.17 
> timeJcl 
    user system elapsed 
    29.80 0.02 30.28 
+0

我感谢你的帮助。 (特别是测试上面的答案!),但我能够使我的算法,它使用一个while循环,运行。 – Jonkie

+0

好的,我建议你发布自己的代码作为答案,这样你就可以告诉我们你的解决方案; – digEmAll

+0

我已经编辑了我的初步建议在答案。 – Jonkie

2

如果你不需要2 3 3 1 4产生2 3 3 4(即,等于没有增加),你可以使用一个很好的降低

test <- c(2,4,7,2,3,1,8) 
unique(Reduce(max, as.list(test), accumulate = TRUE)) 
[1] 2 4 7 8 

如果你想在重复,我敢肯定有一个更好的方式来做到这一点,但

test <- c(2,4,4,7,2,3,1,8) 
reduce = Reduce(max, as.list(test), accumulate = TRUE) 
df = data.frame(o = test, reduce = reduce) 
df[df$o == df$reduce, "o"] 
[1] 2 4 4 7 8 

将其拉出。

+0

这太棒了!我不是一个真正的功能程序员,所以我甚至没有想到要减少,但这绝对是一种方法。 +1 – digEmAll

+1

嗨,感谢您的回答我还发现了另一种方法来做到这一点,这基本上归结为您的方法,这是'独特的(cummax(测试))' – Jonkie

+0

哦太棒了!比我的好得多,大概它也是为基础和数据框架定义的。 –