2013-07-15 43 views
6

Làm cách nào để xóa các mục nhập trùng lặp liên tiếp trong R? Tôi nghĩ rằng with có thể được sử dụng nhưng không thể nghĩ cách sử dụng nó. Minh họa một ví dụ:Xóa các mục nhập trùng lặp liên tiếp

read.table(text = " 
    a  t1 
    b  t2 
    b  t3 
    b  t4 
    c  t5 
    c  t6 
    b  t7 
    d  t8") 

mẫu dữ liệu: D

events time 
     a  t1 
     b  t2 
     b  t3 
     b  t4 
     c  t5 
     c  t6 
     b  t7 
     d  t8 

Required Kết quả:

 events  time 
     a  t1 
     b  t4 
     c  t6 
     b  t7 
     d  t8 

'

Trả lời

0

Một giải pháp trong cơ sở R sử dụng split-apply-kết hợp công trình qua hàm tail trả về phần tử cuối cùng và rle kết hợp với mapply để tạo ra một vector mới của events riêng giữ gìn trật tự trong trường hợp các sự kiện xuất hiện lại:

x <- read.table(text = " events time 
     a  t1 
     b  t2 
     b  t3 
     b  t4 
     c  t5 
     c  t6 
     b  t7 
     d  t8", header = TRUE) 


# create vector of new.events (i.e., preserve reappearing objects) 
occurences <- rle(as.character(x$events))[["lengths"]] 
new.events <- unlist(mapply(rep, x = letters[seq_along(occurences)], times = occurences)) 

# split into sublists per event 
s1 <- split(x, list(new.events)) 

# get last element from list 
s2 <- lapply(s1, tail, n = 1) 

# combine again 
do.call(rbind, s2) 

này sẽ cho kết quả mong muốn.

+0

Cảm ơn sự giúp đỡ của bạn nhưng có một chút thay đổi trong câu hỏi. Đơn đặt hàng vẫn giữ nguyên trong việc sử dụng 'đuôi'? Tôi đã thử điều này và nó sắp xếp các sự kiện theo thứ tự bảng chữ cái. – anu

+0

@anu vui lòng xem cập nhật của tôi, hiện đang hoạt động. – Henrik

2

CHỈNH SỬA: Không chính xác chính xác vì nó chỉ hiển thị một hàng b. Bạn cũng có thể sử dụng nhân đôi() chức năng

x <- read.table(text = " events time 
    a  t1 
    b  t2 
    b  t3 
    b  t4 
    c  t5 
    c  t6 
    d  t7", header = TRUE) 
#Making sure the data is correctly ordered! 
x <- x[order(x[,1], x[,2]), ]  
x[!duplicated(x[,1], fromLast=TRUE), ] 
+0

Điều này là gần, nhưng nó không hoàn toàn cho kết quả dự định của OP. Tôi không bao giờ biết về 'fromLast = TRUE' mặc dù - khá gọn gàng. – thelatemail

+0

Oh darn! Có hai hàng b! – Xachriel

12

Tuy nhiên, một ai khác, giả sử bạn data.frmae được đặt tên d:

d[cumsum(rle(as.numeric(d[,1]))$lengths),] 
    V1 V2 
1 a t1 
4 b t4 
6 c t6 
7 b t7 
8 d t8 
+0

+1 Đây cũng sẽ là câu trả lời của tôi. Tôi đọc câu hỏi OP và khi họ nói * xóa các mục trùng lặp liên tiếp * Tôi đã nghĩ đến mục đầu tiên sử dụng 'cumsum (rle (df $ Event) $ lengths) - rle (df $ Event) $ lengths + 1' –

+0

+ 1, chắc chắn tốt hơn sau đó kết hợp hơi khó khăn của tôi của 'rle',' mapply', 'split',' tail', 'do.call', ... – Henrik

0

Và đối với biện pháp tốt, sử dụng headtail:

dat[with(dat,c(tail(events,-1) != head(events,-1),TRUE)),] 

    events time 
1  a t1 
4  b t4 
6  c t6 
7  b t7 
8  d t8 
Các vấn đề liên quan