2015-09-28 18 views
11

In this blog post, Paul Hiemstra cho biết cách tổng hợp hai cột bằng cách sử dụng dplyr::mutate_. Sao chép/dán-ing bộ phận liên quan:Sử dụng 'mutate_' để tổng hợp một loạt các cột hàng khôn ngoan

library(lazyeval) 
f = function(col1, col2, new_col_name) { 
    mutate_call = lazyeval::interp(~ a + b, a = as.name(col1), b = as.name(col2)) 
    mtcars %>% mutate_(.dots = setNames(list(mutate_call), new_col_name)) 
} 

cho phép một để rồi thực hiện:

head(f('wt', 'mpg', 'hahaaa')) 

Tuyệt vời!

Tôi tiếp tục với câu hỏi (xem nhận xét) về cách có thể mở rộng cột này thành 100 cột, vì nó không rõ ràng (đối với tôi) cách người ta có thể thực hiện mà không phải nhập tất cả tên phương pháp trên. Paul đã được loại, đủ để thưởng thức tôi và cung cấp câu trả lời này (cảm ơn!):

# data 
df = data.frame(matrix(1:100, 10, 10)) 
names(df) = LETTERS[1:10] 

# answer 
sum_all_rows = function(list_of_cols) { 
    summarise_calls = sapply(list_of_cols, function(col) { 
    lazyeval::interp(~col_name, col_name = as.name(col)) 
    }) 
    df %>% select_(.dots = summarise_calls) %>% mutate(ans1 = rowSums(.)) 
} 
sum_all_rows(LETTERS[sample(1:10, 5)]) 

Tôi muốn cải thiện câu trả lời này trên những điểm sau:

  1. Các cột khác đã mất hết. Tôi muốn giữ chúng.

  2. Nó sử dụng rowSums() trong đó có cưỡng chế data.frame để một ma trận mà tôi muốn tránh.

    Ngoài ra tôi không chắc liệu việc sử dụng các cú pháp . trong vòng không do() được khuyến khích hay không? Vì . trong phạm vi mutate() dường như không thích ứng với chỉ những hàng khi được sử dụng với group_by().

  3. Và quan trọng nhất, làm cách nào để tôi có thể thực hiện tương tự bằng cách sử dụng mutate_() thay vì mutate()?

tôi thấy this answer, vốn là biểu điểm 1, nhưng không may, cả hai dplyr câu trả lời sử dụng rowSums() cùng với mutate().


PS: Tôi vừa đọc Hadley's comment under that answer. IIUC, 'định dạng lại thành dạng dài + nhóm bằng + tổng + định dạng lại thành dạng rộng' là cách giới thiệu dplyr cho các loại hoạt động này?

+0

Không cần cho 'thư viện (lazyeval)' khi bạn rõ ràng đủ điều kiện sử dụng của nó anyway. –

Trả lời

7

Dưới đây là một cách tiếp cận khác nhau:

library(dplyr); library(lazyeval) 
f <- function(df, list_of_cols, new_col) { 
    df %>% 
    mutate_(.dots = ~Reduce(`+`, .[list_of_cols])) %>% 
    setNames(c(names(df), new_col)) 
} 

head(f(mtcars, c("mpg", "cyl"), "x")) 
# mpg cyl disp hp drat wt qsec vs am gear carb x 
#1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 27.0 
#2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 27.0 
#3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 26.8 
#4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 27.4 
#5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 26.7 
#6 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 24.1 

Về điểm của bạn:

  • cột khác được lưu giữ
  • Nó không sử dụng rowSums
  • Bạn đang yêu cầu đặc biệt cho một hoạt động hàng khôn ngoan ở đây vì vậy tôi không chắc chắn (chưa) làm thế nào một group_by có thể làm bất kỳ tác hại khi sử dụng . bên mutate/mutate_
  • Nó làm cho sử dụng mutate_
+0

Tuyệt vời! Trên '.' với' group_by() ', tôi chỉ thấy nó lạ. Ví dụ như trường hợp, tính toán tổng hàng và chia chúng bằng tổng tối đa trong nhóm .. Tôi đoán bạn sẽ tính toán tổng hàng và sau đó nhóm theo và nhận tỷ lệ? Nếu vậy, tôi thấy nó kỳ quặc (không thể thực hiện nó trong một bước bằng cách sử dụng biến đổi, nhưng sử dụng 'do()'). Nhưng có lẽ đó là do thiết kế, không phải lo lắng. Cảm ơn. – Arun

+0

Xin chào @docendo discimus. Câu trả lời chính xác. Bạn có biết nếu trong các bản phát hành gần đây của dplyr có một số hàm bổ sung một cột làm tổng các cột phù hợp với một số biểu thức chính quy không? – agenis

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