2016-03-22 29 views
9

Tôi thường phải tạo một cuộc gọi hàm bên trong một hàm khác, sau đó sẽ được đánh giá. Tôi có xu hướng sử dụng eval(parse(text = "what_needs_to_be_done")) cho điều đó, với văn bản được tạo bằng cách sử dụng paste0(). Tuy nhiên, điều này không giống như một cách tiếp cận tốt. Dưới đây là ví dụ:R: lập trình tạo cuộc gọi hàm

select_data <- function(x, A = NULL, B = NULL, C = NULL) { 
    kall <- as.list(match.call()) 
    vars <- names(kall)[names(kall) %in% c("A", "B", "C")] 
    selection_criteria <- paste0(vars, " == ", kall[vars], collapse = ", ") 
    txt <- paste0("dplyr::filter(x, ", selection_criteria, ")") 
    res <- eval(parse(text = txt)) 
    return(res) 
} 

DF <- data.frame(A = c(1,1,2,2,3,3), B = c(1,2,1,2,1,2), C = c(1,1,1,2,2,2)) 
select_data(DF, A = 2, C = 2) 

Đây chỉ là ví dụ, trong hầu hết các trường hợp, hàm được xây dựng phức tạp và rộng hơn. Tuy nhiên, ví dụ cho thấy vấn đề chung. Những gì tôi làm bây giờ là lần đầu tiên paste0 cùng với cuộc gọi chức năng, cách tôi sẽ nhập nó vào bàn điều khiển và sau đó đánh giá nó.

Tôi đã giả mạo với các phương pháp thay thế khác với substitute, lazyeval, bquote, nhưng tôi không hiểu những gì họ thực sự làm và do đó không thể khiến họ làm việc.

Bạn có thể giúp tôi tìm cách tốt hơn để thực hiện cuộc gọi và sau đó đánh giá nó không?

+0

Dưới đây là các liên kết đến nơi khác phải vật lộn với cùng một loại vấn đề [Dplyr lập trình] (http: // stackoverflow.com/questions/36139624/dplyr-filter-where-hai-cột-trong-dữ liệu-khung-bằng-bằng nhau và [Đánh giá phi tiêu chuẩn] (http://stackoverflow.com/questions/26492280/non-standard- đánh giá-nse-in-dplyrs-lọc-kéo-dữ liệu-từ-mysql). Ngoài ra còn có họa tiết này từ tác giả https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html –

Trả lời

9

Cập nhật 4.29.17 - Sẽ sớm phát hành dplyr 0.6.0 sẽ giải quyết những vấn đề này. Các câu trả lời mới đã được thêm vào các câu hỏi bên dưới. Để biết thêm về lập trình với dplyr, see this vignette.


Bạn có ý tưởng đúng. Bạn có thể để rút ngắn đoạn code một chút với ?filter_ và tranh luận chấm ...:

select_data <- function(x, ...) { 
    kall <- list(...) 
    filter_(.data=x, paste0(names(kall), "==", unlist(kall), collapse="&")) 
} 
select_data(DF, A = 2, C = 2) 
# A B C 
# 1 2 2 2 

cập nhật

Lập trình với dplyr có thể rất khó khăn ngay cả đối với lập trình viên trung gian. Tác giả đã thú nhận rằng những lợi thế của việc đánh giá phi tiêu chuẩn đi kèm với chi phí của sự khó khăn đối với lập trình chức năng. Có một số người sử dụng SO chạy vào cùng một vấn đề:

standard evaluation in dplyr

dplyr function does not work

Using dplyr functions within another function

Major dplyr functions in a function Pass arguments to dplyr functions

dplyr: filter where two columns in data.frame are equal

St eps đã được thực hiện để giải quyết những vấn đề này. Có một số vignette to outline the basic fixes. Theo quan điểm khiêm tốn của tôi, họa tiết thiếu thông tin giải thích về lập trình hàm. Không có một hàm nào được viết làm ví dụ. Nó cũng không giải quyết bất kỳ ví dụ gây nhầm lẫn nào thường xuất hiện. Hy vọng rằng, với sự gia tăng trong các cuộc gọi để sửa chữa NSE, cuối cùng chúng tôi có thể nhận được một phản ứng đầy đủ.

Ví dụ cuối cùng về sự lộn xộn mà việc đánh giá phi tiêu chuẩn có thể gây ra trong lập trình, tôi đã cố gắng giải quyết một giải pháp cho người dùng này một lúc không có kết quả. Nó chỉ đơn giản là yêu cầu để sử dụng summarise lập trình:

Sub-function in grouping function using dplyr

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