2015-10-05 116 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

哦太棒了!比我的好得多,大概它也是爲基礎和數據框架定義的。 –