2016-02-06 14 views
11

Trong R, tôi muốn tóm tắt dữ liệu của mình sau khi nhóm nó dựa trên các biến số x (còn gọi là mỗi nhóm dữ liệu tương ứng với tập hợp con dữ liệu có giá trị x liên tiếp) giống nhau). Ví dụ, hãy xem xét các khung dữ liệu sau đây, nơi tôi muốn để tính trung bình giá trị y trong mỗi lần chạy của x:Sử dụng rle để nhóm bằng cách chạy khi sử dụng dplyr

(dat <- data.frame(x=c(1, 1, 1, 2, 2, 1, 2), y=1:7)) 
# x y 
# 1 1 1 
# 2 1 2 
# 3 1 3 
# 4 2 4 
# 5 2 5 
# 6 1 6 
# 7 2 7 

Trong ví dụ này, biến x có chạy có độ dài 3, sau đó 2, sau đó 1, và cuối cùng là 1, lấy các giá trị 1, 2, 1 và 2 trong bốn giá trị đó. Các phương tiện tương ứng của y trong các nhóm 2, 4,5, 6, và 7.

Nó rất dễ dàng để thực hiện hoạt động nhóm này trong cơ sở R sử dụng tapply, đi dat$y như dữ liệu, sử dụng rle để tính toán số lượng chạy từ dat$x, và đi qua các chức năng tóm tắt mong muốn:

tapply(dat$y, with(rle(dat$x), rep(seq_along(lengths), lengths)), mean) 
# 1 2 3 4 
# 2.0 4.5 6.0 7.0 

tôi figured tôi sẽ có thể khá trực tiếp thực hiện trên logic này để dplyr, nhưng những nỗ lực của tôi cho đến nay đều kết thúc trong các lỗi:

library(dplyr) 
# First attempt 
dat %>% 
    group_by(with(rle(x), rep(seq_along(lengths), lengths))) %>% 
    summarize(mean(y)) 
# Error: cannot coerce type 'closure' to vector of type 'integer' 

# Attempt 2 -- maybe "with" is the problem? 
dat %>% 
    group_by(rep(seq_along(rle(x)$lengths), rle(x)$lengths)) %>% 
    summarize(mean(y)) 
# Error: invalid subscript type 'closure' 

Để hoàn chỉnh, tôi có thể reimplement id rle chạy bản thân mình sử dụng cumsum, head, và tail để làm được việc này, nhưng nó làm cho các mã nhóm khó khăn hơn để đọc và liên quan đến một chút reinventing the wheel:

dat %>% 
    group_by(run=cumsum(c(1, head(x, -1) != tail(x, -1)))) %>% 
    summarize(mean(y)) 
#  run mean(y) 
# (dbl) (dbl) 
# 1  1  2.0 
# 2  2  4.5 
# 3  3  6.0 
# 4  4  7.0 

Điều gì gây ra mã nhóm rle dựa trên của tôi bị lỗi trong dplyr và có giải pháp nào cho phép tôi tiếp tục sử dụng rle khi nhóm theo id chạy không?

Trả lời

7

Một lựa chọn có vẻ là việc sử dụng các {} như trong:

dat %>% 
    group_by(yy = {yy = rle(x); rep(seq_along(yy$lengths), yy$lengths)}) %>% 
    summarize(mean(y)) 
#Source: local data frame [4 x 2] 
# 
#  yy mean(y) 
# (int) (dbl) 
#1  1  2.0 
#2  2  4.5 
#3  3  6.0 
#4  4  7.0 

Nó sẽ được tốt đẹp nếu tương lai dplyr phiên bản cũng đã có một tương đương với chức năng data.table của rleid.


tôi nhận thấy rằng vấn đề này xảy ra khi sử dụng một data.frame hoặc tbl_df đầu vào nhưng không, khi sử dụng một tbl_dt hay data.table đầu vào:

dat %>% 
    tbl_df %>% 
    group_by(yy = with(rle(x), rep(seq_along(lengths), lengths))) %>% 
    summarize(mean(y)) 
Error: cannot coerce type 'closure' to vector of type 'integer' 

dat %>% 
    tbl_dt %>% 
    group_by(yy = with(rle(x), rep(seq_along(lengths), lengths))) %>% 
    summarize(mean(y)) 
Source: local data table [4 x 2] 

    yy mean(y) 
    (int) (dbl) 
1  1  2.0 
2  2  4.5 
3  3  6.0 
4  4  7.0 

Tôi đã báo cáo này như một issue trên trang github dplyr của.

+2

Có vẻ như vấn đề đã bị đóng làm ví dụ về https://github.com/hadley/dplyr/issues/1400 mà chúng dường như đang hoạt động. – josliber

+1

Điều này thật tuyệt. Bạn có thể giải thích hoặc hướng dẫn tôi đến tài liệu về cách "{}" hoạt động trong cuộc gọi nhóm_by ở đây không? Googling "dplyr {}" không đặc biệt hiệu quả nhưng có lẽ có một cái tên lạ mắt cho loại cuộc gọi này ở đây? Cảm ơn! – Jordan

+3

@ Jordan, đó không phải là chức năng cụ thể của dplyr.Đó là từ cơ sở R và bạn có thể kiểm tra 'help (" {")' –

2

Nếu bạn tạo một cách rõ ràng một nhóm biến g nó ít nhiều tác phẩm:

> dat %>% transform(g=with(rle(dat$x),{ rep(seq_along(lengths), lengths)}))%>%         
group_by(g) %>% summarize(mean(y)) 
Source: local data frame [4 x 2] 

     g mean(y) 
    (int) (dbl) 
1  1  2.0 
2  2  4.5 
3  3  6.0 
4  4  7.0 

tôi đã sử dụng transform đây vì mutate ném một lỗi.

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