2015-05-07 20 views
5

Làm cách nào để sử dụng mutate (giả định rằng tôi đang tìm kiếm đánh giá tiêu chuẩn trong trường hợp của mình, và do đó không hoàn toàn tự tin vào thời điểm này) khi sử dụng chức năng chấp nhận một danh sách các tên biến, như thế này:dplyr: đánh giá tiêu chuẩn cho biến đổi với tên biến được trích dẫn

createSum = function(data, variableNames) { 
    data %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(variableNames), collapse =",")))) 

} 

Dưới đây là một MWe rằng dải chức năng logic cốt lõi của nó và chứng minh những gì tôi đang cố gắng để đạt được:

library(dplyr) 
library(lazyeval) 

# function to make random table with given column names 
makeTable = function(colNames, sampleSize) { 
    liSample = lapply(colNames, function(week) { 
    sample = rnorm(sampleSize) 
    }) 
    names(liSample) = as.character(colNames) 
    return(tbl_df(data.frame(liSample, check.names = FALSE))) 
} 

# create some sample data with the column name patterns required 
weekDates = seq.Date(from = as.Date("2014-01-01"), 
        to = as.Date("2014-08-01"), by = "week") 
dfTest = makeTable(weekDates, 10) 

# test mutate on this table 
dfTest %>% 
    mutate_(sumvar = interp(~ sum(var, na.rm = TRUE), 
          var = as.name(paste(as.character(weekDates), collapse =",")))) 

Dự kiến ​​sản lượng ở đây là những gì sẽ được trả lại bởi:

rowSums(dfTest[, as.character(weekDates)]) 
+0

Bạn xác định 'makeTable' nhưng sau đó gọi 'makeDataFrame'. Đây có phải là chức năng giống nhau không? Sẽ rất hữu ích khi mô tả đầu ra mà bạn mong đợi cho đầu vào mẫu này (đặt một hạt giống cho dữ liệu có thể tái tạo). – MrFlick

+0

@MrFlick Cảm ơn. Đã thay đổi tên hàm. Không có gì lạ mắt được mong đợi, chỉ là 'tổng hợp' của tất cả các biến có tên biến được chuyển đến hàm, theo hàng. Sẽ cập nhật với đầu ra dự kiến. – tchakravarty

Trả lời

5

Tôi nghĩ rằng đây là những gì bạn đang sau

createSum = function(data, variableNames) { 
    data %>% 
     mutate_(sumvar = paste(as.character(variableNames), collapse ="+")) 
} 
createSum(dfTest, weekDates) 

nơi chúng tôi chỉ cung cấp một giá trị nhân vật chứ không phải là interp vì bạn có thể không chuyển vào danh sách các tên như một tham số duy nhất cho một hàm. Ngoài ra, sum() sẽ thực hiện một số lần thu gọn không mong muốn vì các thao tác không được thực hiện theo hàng, chúng được chuyển vào các cột của vectơ tại một thời điểm.

Vấn đề khác với ví dụ này là bạn đặt check.names=FALSE trong data.frame có nghĩa là bạn đã tạo tên cột không thể là ký hiệu hợp lệ. Bạn có thể bao bọc rõ ràng tên biến của mình trong các dấu tích sau nếu bạn thích

createSum(dfTest , paste0("`", weekDates,"`")) 

nhưng nói chung tốt hơn là không nên sử dụng tên không hợp lệ.

+0

Cảm ơn, điều này sẽ hoạt động, nhưng nếu chức năng không có biểu tượng toán tử tiện dụng thì sao? Thứ hai, làm thế nào sau đó tôi sẽ vượt qua một danh sách các đối số theo tên để '...' trong một chức năng? Các ví dụ duy nhất của đánh giá tiêu chuẩn tôi đã thấy liên quan đến một tên biến. – tchakravarty

+0

Không dễ để nói về giả thuyết, mọi chức năng có thể khác nhau. Nhưng phương pháp xây dựng chuỗi này sẽ làm việc cho nhiều hàm khác ('tổng hợp 'là một phần của một ngoại lệ). Chỉ cần dán có thể trông giống như 'paste0 (" funname (", paste (vars, collapse =", "),") ")' – MrFlick

+0

Vâng, như tôi sợ, trông giống như cú pháp khủng khiếp (không phải lỗi của bạn!) . Tôi không nghĩ rằng tôi hiểu mô hình rất tốt - tất cả những gì tôi muốn có thể làm là đánh giá các ký hiệu biến đổi trong môi trường của 'data_frame'. Chắc chắn có một cách neater để làm điều này mà không cần đến xây dựng biểu hiện cồng kềnh hoặc 'eval (phân tích cú pháp (văn bản =)'. – tchakravarty

1

Tôi không biết nếu điều này là một "chính thức bị xử phạt" dplyr bằng cách nào, nhưng đây là một khả năng:

weekDates = as.character(weekDates) # more convenient 

dfTest %>% mutate(sumvar = Reduce(`+`, lapply(weekDates, get, .))) 
#or 
dfTest %>% mutate(sumvar = rowSums(as.data.frame(lapply(weekDates, get, .)))) 

này mang khả năng hình phạt hiệu suất đáng kể, tùy thuộc vào cách sử dụng cụ thể của bạn - ngoài dplyr Sao chép thường xuyên toàn bộ dữ liệu Tôi nghĩ rằng nó cũng sao chép nó lần thứ hai trong suốt quá trình tính toán nội bộ đó. Bạn có thể xem xét data.table để tránh sao chép thêm xung quanh bằng cách thêm cột tại chỗ (và sử dụng .SDcols để tránh bản sao thứ hai) + bạn sẽ nhận được cú pháp được cho là tốt hơn.

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