2017-03-27 70 views
5

Więc jeśli wejście jest wektorem takich jakJak mogę odwrócić numery TYLKO w wektorze, jeśli są one sekwencyjne?

v <- (1, 2, 3, 7, 2, 8, 9) 

Wyjście byłoby

(3, 2, 1, 7, 2, 9, 8) 

Próbowałem przy użyciu zagnieżdżony za i jeśli pętli z warunkiem jako funkcji is.sorted, ale nie mają odniosło sukces.

+1

zobacz także: [Jak podzielić wektor na grupy regularnych kolejnych sekwencjach?] (Http: //stackoverflow.com/questions/5222061/how-to-partition-a-vec sekwencje-do-grup-regularnych-kolejnych sekwencji) – Henrik

+0

... co według mnie jest miłym, kanonicznym postem dla 'cumsum (... diff (...) idiom. – Henrik

Odpowiedz

8

Z przykładowych danych

x <- c(1, 2, 3, 7, 2, 8, 9) 

można podzielić na „grupy” sekwencyjnych z

grp <- cumsum(!c(TRUE, diff(x)==1)) 
grp 
# [1] 0 0 0 1 2 3 3 

Zasadniczo patrzymy na Różnica względem poprzedniego elementu i śledzenia zmian w każdej chwili, że wartość ta nie jest równa się 1.

Możesz użyć tej informacji o grupie, aby zmienić kolejność tych wartości za pomocą ave (to transformacja wewnątrzgrupowa).

revsort<-function(...) sort(...,decreasing=TRUE) 
ave(x, grp, FUN=revsort) 
# [1] 3 2 1 7 2 9 8 
5

Możemy również zrobić:

x <- c(0, which(diff(vec) != 1), length(vec)) 
unlist(sapply(seq(length(x) - 1), function(i) rev(vec[(x[i]+1):x[i+1]]))) 

#[1] 3 2 1 7 2 9 8 

Chodzi o to, aby najpierw wyciąć wektor oparty na stanowiskach kolejnymi numerami. Następnie przechodzimy przez te cięcia i stosujemy rev.


danych

vec <- c(1, 2, 3, 7, 2, 8, 9) 

Benchmarking

library(microbenchmark) 
vec1 <- c(1, 2, 3, 7, 2, 8, 9) 
vec2 <- c(1:1000, sample.int(100, 10), 5:500, sample.int(100, 10), 100:125) 

f_MrFlick <- function(x){ 
    revsort<-function(...) sort(...,decreasing=TRUE) 
    grp <- cumsum(!c(TRUE, diff(x)==1)) 
    ave(x, grp, FUN=revsort) 
} 

f_989 <- function(vec){ 
    x <- c(0, which(diff(vec) != 1), length(vec)) 
    unlist(sapply(seq(length(x) - 1), function(i) rev(vec[(x[i]+1):x[i+1]]))) 
} 

all(f_MrFlick(vec1)==f_989(vec1)) 
# [1] TRUE 
all(f_MrFlick(vec2)==f_989(vec2)) 
# [1] TRUE 

length(vec1) 
# [1] 7 
microbenchmark(f_MrFlick(vec1), f_989(vec1)) 
# Unit: microseconds 
      # expr  min  lq  mean median  uq  max neval 
# f_MrFlick(vec1) 287.006 297.0585 305.6340 302.833 312.6695 479.912 100 
    # f_989(vec1) 113.348 119.7645 124.7901 121.903 127.0360 268.186 100 
# -------------------------------------------------------------------------- 
length(vec2) 
# [1] 1542 
microbenchmark(f_MrFlick(vec2), f_989(vec2)) 
# Unit: microseconds 
      # expr  min  lq  mean median  uq  max neval 
# f_MrFlick(vec2) 1532.553 1565.2745 1725.7540 1627.937 1698.084 3914.149 100 
    # f_989(vec2) 426.874 454.6765 546.9115 466.439 489.322 2634.383 100