2013-11-15 19 views
9

में मानों की लगातार घटनाओं की गणना करें, मैं समान मूल्यों के प्रत्येक भाग के भीतर एक अनुक्रमिक संख्या बनाना चाहता हूं, जैसे घटनाओं के काउंटर, जो कि वर्तमान पंक्ति में मान पिछली पंक्ति से अलग होने के बाद पुनरारंभ होता है।आर: एक कॉलम

कृपया इनपुट का एक उदाहरण और नीचे अपेक्षित आउटपुट पाएं। 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 

मेरा प्रश्न बहुत करने के लिए यह एक समान है।

उत्तर

27

आप sequence और rle उपयोग करने की आवश्यकता:

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

चीयर्स, कि एक आकर्षण की तरह काम करता है! आप $ लंबाई के हिस्से के बारे में कैसे जानते हैं? क्या अन्य गुण हैं? (उन्हें आर डॉक्स में न देखें)। – Richard

+2

@ रिचर्ड, '? Rle' के लिए प्रलेखन के "मान" खंड को देखें। दो मान लौटे ('वर्ग'" राल "की 'सूची' में) 'लंबाई' और' मान' हैं। – A5C1D2H2I1M1N2O1R2T1

13

नीचे लिखा समारोह के एक कुशल और अधिक सरल संस्करण rleid बुलाया data.table पैकेज में अब उपलब्ध है। कि का उपयोग करना, यह सिर्फ है:

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

उपयोग और उदाहरण के बारे में अधिक के लिए ?rleid देखें। इस पोस्ट को अपडेट करने के सुझाव के लिए @ हेनरिक के लिए धन्यवाद।


rle निश्चित रूप से यह करने के लिए (+1 @ आनंद के) सबसे आसान तरीका है। लेकिन बड़ा डेटा पर कोई बेहतर (गति के मामले में) कर सकता है। बड़ा डेटा पर

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 

बेंचमार्किंग:: आप इस प्रकार data.table से duplist और vecseq कार्य (नहीं निर्यात) का उपयोग कर सकते

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

अपने सुपर-डुपर-गुप्त कार्यों का उपयोग करके उचित नहीं है! :-(....... +1 – A5C1D2H2I1M1N2O1R2T1

+0

@ अरुण, धन्यवाद यह एक छोटा सा डेटासेट है जिस पर मैं काम कर रहा हूं, लेकिन यह भविष्य में निश्चित रूप से काम में आ जाएगा! मुझे खेद है, मैं केवल एक जवाब स्वीकार कर सकता हूं! :( – Richard

+2

हाय @ अरुण - मुझे लगता है कि 'data.table' संस्करण के नवीनतम संस्करण में डुप्लिकेट नहीं है 1.9.2 – vrajs5

संबंधित मुद्दे