2013-08-16 26 views
5

Tôi đang cố gắng để tìm chạy của năm trong một khung dữ liệu (lý tưởng sử dụng plyr)Finding dao động trong chạy của số

Tôi muốn nhận được từ này:

require(plyr) 

dat<-data.frame(
    name=c(rep("A", 11), rep("B", 11)), 
    year=c(2000:2010, 2000:2005, 2007:2011) 
) 

Để này:

out<-data.frame(
    name=c("A", "B", "B"), 
    range=c("2000-2010", "2000-2005", "2007-2011")) 

Thật dễ dàng đủ để xác định xem mỗi nhóm có một hoạt động liên tục của năm:

ddply(dat, .(name), summarise, 
     continuous=(max(year)-min(year))+1==length(year)) 

Tôi làm cách nào để chia nhỏ nhóm "B" thành hai phạm vi?

Bất kỳ ý tưởng hoặc chiến lược nào sẽ thực sự được đánh giá cao.

Cảm ơn

Trả lời

7

Cho dù bạn sử dụng một chức năng từ "plyr" hoặc từ cơ sở R, bạn cần phải đầu tiên thiết lập một số nhóm. Một cách để phát hiện sự thay đổi trong nhóm từ năm của bạn là tuần tự là tìm nơi diff không bằng 1. diff tạo ra một vectơ có chiều dài ít hơn vectơ đầu vào, vì vậy chúng ta sẽ khởi tạo với "1" và lấy số cumsum của kết quả.

Đưa rằng ngụm một lời giải thích vào thực tế, bạn có thể thử một cái gì đó như thế này:

dat$id2 <- cumsum(c(1, diff(dat$year) != 1)) 

Từ đây, bạn có thể sử dụng aggregate hoặc chức năng nhóm yêu thích của bạn để có được những kết quả bạn đang tìm kiếm.

aggregate(year ~ name + id2, dat, function(x) paste(min(x), max(x), sep = "-")) 
# name id2  year 
# 1 A 1 2000-2010 
# 2 B 2 2000-2005 
# 3 B 3 2007-2011 

Để sử dụng range với aggregate, bạn cần thay đổi sep-collapse, như sau:

aggregate(year ~ name + id2, dat, function(x) paste(range(x), collapse = "-")) 
+1

+1 giải pháp rất hay. –

+0

Tuyệt vời - Tôi chưa bao giờ nghĩ về điều đó. Đối với plyr tôi có thể hoàn thành nó với ddply (dat,. (Tên, id2), tóm tắt, dán (min (năm), ":", max (năm), sep = "")). –

+0

@EdG hoặc 'ddply (dat," id2 ", tóm tắt, Phạm vi = dán (phạm vi (năm), thu gọn =" - "))' –

2

Tooting sừng của riêng tôi, cgwtools::seqle thể được sử dụng để xác định chia tách. Chạy một vòng lặp hoặc *apply qua names yếu tố, và đối với từng trường hợp,

foo <- seqle(dat$year, incr=1) 

Sau đó length(foo$lengths) sẽ cung cấp cho bạn số lượng các nhóm, và phạm vi của năm có thể dễ dàng xây dựng lại từ foo$values.

yeargroups <- sapply(length(foo$lengths), function(x) c(foo$values[x],(foo$values[x]+foo$lengths[x]-1))) 

Chỉ đề xuất trường hợp này trong trường hợp ai đó có tình huống tương tự với các thông số khác nhau hoặc phân mục mong muốn.

+0

+1. Tôi đã đề cập đến nó, nhưng tôi nghĩ rằng tôi sẽ cung cấp cho bạn một cơ hội để hiển thị gói của bạn :) – A5C1D2H2I1M1N2O1R2T1

Các vấn đề liên quan