2013-11-15 22 views
9

Geçerli satırdaki değer bir önceki satırdan farklı olduğunda yeniden başlayan bir yineleme değeri gibi, her bir eşit değer aralığında bir sıralı sayı oluşturmak istiyorum.R: tek bir sütundaki değerlerin birbirini izleyen yinelemelerini sayma

Lütfen giriş ve beklenen çıktıya bir örnek aşağıda bulabilirsiniz. Cumulative sequence of occurrences of values:

dataset <- data.frame(input = c("a","b","b","a","a","c","a","a","a","a","b","c")) 
dataset$counter <- c(1,1,2,1,2,1,1,2,3,4,1,1) 
dataset 

# input counter 
# 1  a  1 
# 2  b  1 
# 3  b  2 
# 4  a  1 
# 5  a  2 
# 6  c  1 
# 7  a  1 
# 8  a  2 
# 9  a  3 
# 10  a  4 
# 11  b  1 
# 12  c  1 

Sorum bu bir çok benzer.

cevap

27

Sen sequence ve rle kullanmak gerekir:

> sequence(rle(as.character(dataset$input))$lengths) 
[1] 1 1 2 1 2 1 1 2 3 4 1 1 
+0

Cheers, bir cazibe gibi çalışır! $ Uzunlukları bölümünü nereden biliyorsunuz? Başka özellikleri var mı (R Dokümanlar'da onları görmeyin). – Richard

+2

@Richard, 'rle' için belgelerin" Değer "bölümüne bakın. Döndürülmüş iki değer ("sınıf" ın "listesindeki") uzunluklar ve değerlerdir. – A5C1D2H2I1M1N2O1R2T1

13

aşağıda yazılı fonksiyonun bir verimli ve daha anlaşılır sürüm rleid denilen data.table pakette artık kullanılabilir. Bu kullanarak, bu sadece:

setDT(dataset)[, counter := seq_len(.N), by=rleid(input)] 

kullanımı ve örnekler üzerinde daha fazla bilgi için ?rleid bakınız. Bu yazıyı güncelleme önerisi için @Henrik teşekkürler.


rle kesinlikle (Ananda en @ +1) bunu yapmak için en uygun yoldur. Ancak daha büyük veriler üzerinde daha iyi (hız açısından) yapılabilir. aşağıdaki şekilde data.table den (değil ihraç) duplist ve vecseq işlevleri kullanabilirsiniz:

require(data.table) 
arun <- function(y) { 
    w = data.table:::duplist(list(y)) 
    w = c(diff(w), length(y)-tail(w,1L)+1L) 
    data.table:::vecseq(rep(1L, length(w)), w, length(y)) 
} 

x <- c("a","b","b","a","a","c","a","a","a","a","b","c") 
arun(x) 
# [1] 1 1 2 1 2 1 1 2 3 4 1 1 

Kıyaslama büyük verilere:

set.seed(1) 
x <- sample(letters, 1e6, TRUE) 
# rle solution 
ananda <- function(y) { 
    sequence(rle(y)$lengths) 
} 

require(microbenchmark) 
microbenchmark(a1 <- arun(x), a2<-ananda(x), times=100) 
Unit: milliseconds 
      expr  min  lq median  uq  max neval 
    a1 <- arun(x) 123.2827 132.6777 163.3844 185.439 563.5825 100 
a2 <- ananda(x) 1382.1752 1899.2517 2066.4185 2247.233 3764.0040 100 

identical(a1, a2) # [1] TRUE 
+10

Süper-duper-gizli işlevlerinizi kullanarak adil değil! :-(....... +1 – A5C1D2H2I1M1N2O1R2T1

+0

@Arun, bu biraz daha küçük veri kümesi üzerinde çalıştığım için teşekkürler, ama kesinlikle gelecekte kullanışlı olacak! Üzgünüm, sadece bir cevabı kabul edebilirim! :( – Richard

+2

Merhaba @Arun - 'data.table' sürümünün son sürümünde duplist bulunmuyor. 1.9.2 – vrajs5

İlgili konular