2014-12-29 11 views
16

Tôi đang viết một hàm mà người dùng được yêu cầu xác định một hoặc nhiều biến nhóm trong lệnh gọi hàm. Dữ liệu sau đó được nhóm lại bằng cách sử dụng dplyr và nó hoạt động như mong đợi nếu chỉ có một biến nhóm, nhưng tôi đã không tìm ra cách thực hiện nó với nhiều biến nhóm.dplyr :: group_by_ với đầu vào chuỗi ký tự của một số tên biến

Ví dụ:

x <- c("cyl") 
y <- c("cyl", "gear") 
dots <- list(~cyl, ~gear) 

library(dplyr) 
library(lazyeval) 

mtcars %>% group_by_(x)    # groups by cyl 
mtcars %>% group_by_(y)    # groups only by cyl (not gear) 
mtcars %>% group_by_(.dots = dots) # groups by cyl and gear, this is what I want. 

tôi đã cố gắng để biến y vào giống như dots sử dụng:

mtcars %>% group_by_(.dots = interp(~var, var = list(y))) 
#Error: is.call(expr) || is.name(expr) || is.atomic(expr) is not TRUE 

Làm thế nào để sử dụng một chuỗi đầu vào người dùng xác định> 1 tên biến (như y trong ví dụ) để nhóm dữ liệu bằng cách sử dụng dplyr?

(Câu hỏi này được bằng cách nào đó liên quan đến this one nhưng không trả lời ở đây.)

+0

Đây là lý do tại sao bạn nên bắt đầu sử dụng 'data.table' :)' as.data.table (mtcars) [, sum (carb), y] 'j/k. Câu hỏi hay. –

+2

Tôi có thể, một số ngày :) Nhưng bây giờ tôi sẽ gắn bó với dplyr .. –

Trả lời

17

Không cần interp đây, chỉ cần sử dụng as.formula để chuyển đổi xâu kí tự sang công thức:

dots = sapply(y, . %>% {as.formula(paste0('~', .))}) 
mtcars %>% group_by_(.dots = dots) 

Lý do tại sao interp của bạn phương pháp tiếp cận không hoạt động là biểu thức cung cấp cho bạn các nội dung sau:

~list(c("cyl", "gear")) 

- không phải những gì bạn muốn. Bạn có thể, tất nhiên, sapplyinterp qua y, đó sẽ là tương tự như sử dụng as.formula trên:

dots1 = sapply(y, . %>% {interp(~var, var = .)}) 

Nhưng, trên thực tế, bạn cũng có thể trực tiếp vượt qua y:

mtcars %>% group_by_(.dots = y) 

Các dplyr vignette on non-standard evaluation đi vào chi tiết hơn và giải thích sự khác biệt giữa các cách tiếp cận này.

+0

@David Tôi sẽ không sử dụng nó. Tôi chỉ hiển thị nó để trả lời câu hỏi trực tiếp của OP về cách chuyển đổi vectơ ký tự thành một vectơ công thức. Điều đó nói rằng, có * là * một sự khác biệt (các công thức đi kèm với một môi trường kèm theo), và nói chung tài liệu dplyr khuyến cáo sử dụng các công thức trên chuỗi ký tự. Tuy nhiên, trong trường hợp này, môi trường là một chút vô dụng. –

+0

Cảm ơn bạn rất nhiều vì đã viết bài này, @ Konrad-Rudolph. Nó đã cứu tôi rất nhiều đau đớn. Tôi đang gặp khó khăn trong việc hiểu chức năng của bạn ... ... "." trong đó? – SFuj

0

slice_rows() từ purrrlyr gói (https://github.com/hadley/purrrlyr) nhóm một data.frame bằng cách lấy một vector của tên cột (chuỗi) hoặc vị trí (số nguyên):

y <- c("cyl", "gear") 
mtcars_grp <- mtcars %>% purrrlyr::slice_rows(y) 

class(mtcars_grp) 
#> [1] "grouped_df" "tbl_df"  "tbl"  "data.frame" 

group_vars(mtcars_grp) 
#> [1] "cyl" "gear" 

Đặc biệt hữu ích bây giờ mà group_by_() đã được khấu hao.

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