2015-05-19 11 views
6

Czy istnieje szybszy sposób tworzenia indeksu licznika niż przy użyciu pętli? W przypadku ciągłych przebiegów o równych wartościach indeks powinien być taki sam. Uważam, że pętla jest bardzo powolna, szczególnie gdy dane są tak duże.Dodaj indeks do ciągłych przebiegów o równych wartościach

Dla ilustracji oto wejściowe i sygnał wyjściowy

x <- c(2, 3, 9, 2, 4, 4, 3, 4, 4, 5, 5, 5, 1) 

pożądaną ostateczną licznik:

c(1, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9) 

Należy zauważyć, że non -contiguous biegach różne indeksów. Na przykład. zobacz pożądanych indeksy wartości 2 i 4

mój kod nieefektywne to:

group[1]<-1 
counter<-1 
for (i in 2:n){ 
if (x[i]==x[i-1]){ 
    group[i]<-counter 
}else{ 
    counter<-counter+1 
    group[1]<-counter} 
} 
+0

Thanks TimoSta dla edycji =) – Rens

Odpowiedz

7

Jeśli masz wartości numerycznych tak, można użyć diff i cumsum aby dodać zmiany w wartościach

x <- c(2,3,9,2,4,4,3,4,4,5,5,5,1) 
cumsum(c(1,diff(x)!=0)) 
# [1] 1 2 3 4 5 5 6 7 7 8 8 8 9 
+0

Dziękujemy! Ten kod działa dobrze. =) – Rens

+0

Zdecydowanie szybciej niż moja odpowiedź. Nie można w tej chwili ocenić odpowiedzi Arun na "data.table". – Jota

+0

Dzięki Frank za ten komentarz. Teraz skorzystam z sugestii MrFlicka. Wygląda na to, że potrzebna jest pewna instalacja dla sugestii Arun dla data.table. – Rens

8

Korzystanie data.table, który posiada funkcję rleid():

require(data.table) # v1.9.5+ 
rleid(x) 
# [1] 1 2 3 4 5 5 6 7 7 8 8 8 9 
+1

Dziękujemy za pomoc! =) – Rens

6

Będzie to działać z numerycznej wartości Charakter:

rep(1:length(rle(x)$values), times = rle(x)$lengths) 
#[1] 1 2 3 4 5 5 6 7 7 8 8 8 9 

można być również nieco bardziej wydajny wywołując rle tylko raz (około 2x szybciej) i bardzo niewielka poprawa prędkości może być wykonane przy użyciu rep.int zamiast rep:

y <- rle(x) 
rep.int(1:length(y$values), times = y$lengths) 
+0

Dziękuję. Ten kod również działa! =) – Rens

Powiązane problemy