2016-03-15 15 views
6

Tôi có một tập hợp các vị trí động vật với các khoảng lấy mẫu khác nhau. Những gì tôi muốn làm là nhóm và seqences nơi khoảng thời gian lấy mẫu phù hợp với một tiêu chí nhất định (ví dụ dưới một giá trị nhất định). Hãy để tôi minh họa với một số dữ liệu giả:Phân nhóm các hàng trên cơ sở sự khác biệt hàng trong R

start <- Sys.time() 
timediff <- c(rep(5,3),20,rep(5,2)) 
timediff <- cumsum(timediff) 

# Set up a dataframe with a couple of time values 
df <- data.frame(TimeDate = start + timediff) 

# Calculate the time differences between the rows 
df$TimeDiff <- c(as.integer(tail(df$TimeDate,-1) - head(df$TimeDate,-1)),NA) 

# Define a criteria in order to form groups 
df$TimeDiffSmall <- df$TimeDiff <= 5 

      TimeDate TimeDiff TimeDiffSmall 
1 2016-03-15 23:11:49  5   TRUE 
2 2016-03-15 23:11:54  5   TRUE 
3 2016-03-15 23:11:59  20   FALSE 
4 2016-03-15 23:12:19  5   TRUE 
5 2016-03-15 23:12:24  5   TRUE 
6 2016-03-15 23:12:29  NA   NA 

Trong dữ liệu giả này, hàng 1: 3 thuộc về một nhóm, vì sự chênh lệch thời gian giữa chúng là < = 5 giây. 4 - 6 thuộc nhóm thứ hai, nhưng giả thuyết có thể có một số hàng ở giữa hai nhóm không thuộc về bất kỳ nhóm nào (TimeDiffSmall tương đương với FALSE).

Kết hợp thông tin từ hai câu trả lời SO nhiều (ví dụ: part 1), tôi đã tạo một hàm để giải quyết vấn đề này.

number.groups <- function(input){ 
    # part 1: numbering successive TRUE values 
    input[is.na(input)] <- F 
    x.gr <- ifelse(x <- input == TRUE, cumsum(c(head(x, 1), tail(x, -1) - head(x, -1) == 1)),NA) 
    # part 2: including last value into group 
    items <- which(!is.na(x.gr)) 
    items.plus <- c(1,items+1) 
    sel <- !(items.plus %in% items) 
    sel.idx <- items.plus[sel] 
    x.gr[sel.idx] <- x.gr[sel.idx-1] 
    return(x.gr) 


# Apply the function to create groups 
df$Group <- number.groups(df$TimeDiffSmall) 

      TimeDate TimeDiff TimeDiffSmall Group 
1 2016-03-15 23:11:49  5   TRUE  1 
2 2016-03-15 23:11:54  5   TRUE  1 
3 2016-03-15 23:11:59  20   FALSE  1 
4 2016-03-15 23:12:19  5   TRUE  2 
5 2016-03-15 23:12:24  5   TRUE  2 
6 2016-03-15 23:12:29  NA   NA  2 

Chức năng này thực sự hoạt động để giải quyết vấn đề của tôi. Đây là, nó có vẻ như một cách điên rồ và tân binh để đi về điều này. Có chức năng nào có thể giải quyết vấn đề của tôi chuyên nghiệp hơn không?

+5

Có 'cumsum (c (TRUE, diff (df $ TimeDate)> 5))' làm điều đó cho ví dụ lớn hơn của bạn? – thelatemail

Trả lời

2

Giống như @thelatemail, tôi sẽ sử dụng thông tin sau để nhận ID nhóm. Nó hoạt động vì cumsum() sẽ kết thúc tăng số lượng nhóm mỗi khi nó đạt đến một phần tử đứng trước khoảng thời gian lớn hơn 5 giây.

df$Group <- cumsum(c(TRUE, diff(df$TimeDate) > 5)) 
df$Group 
# [1] 1 1 1 2 2 2 
+0

Hoặc 'cumsum (c (FALSE,! (Diff (df $ TimeDate) <= 5)))' nếu bạn muốn giữ khung lựa chọn theo cách của nó, thay vì cách nó không phải là. – thelatemail

+0

@thelatemail Đó là những gì tôi bắt đầu với thực tế, và khi tôi thấy sau đó tôi cần phải thêm một kết quả (hoặc thay đổi 'FALSE' ban đầu thành' TRUE') để lấy số nhóm bắt đầu bằng một, tôi lật mọi thứ xung quanh dường như là câu thần chú đơn giản hơn. –

+0

Đủ công bằng - điều đó phụ thuộc vào tôi nếu tiêu chí lựa chọn phức tạp. Sau đó phủ nhận nó dễ dàng hơn việc cố gắng đảo ngược nó một cách thủ công và đảm bảo tất cả các '&' và s '' 'đều đúng. – thelatemail

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