2012-05-20 42 views
17

Tôi bị kẹt với một vấn đề R nhỏ với data.table. Sự giúp đỡ của bạn được đánh giá rất cao. Làm thế nào để làm điều này:Trong R data.table, làm cách nào để chuyển các tham số biến cho một biểu thức?

getResult <- function(dt, expr, gby) { 
    e <- substitute(expr) 
    b <- substitute(gby) 
    return(dt[,eval(e),by=b]) 
} 

v1 <- "Sepal.Length" 
v2 <- "Species" 

dt <- data.table(iris) 
rDT <- getResult(dt, sum(v1, na.rm=TRUE), v2) 

tôi nhận được lỗi sau:

Error in sum(v1, na.rm = TRUE) : invalid 'type' (character) of argument

Bây giờ, cả hai v1v2 có được thông qua từ chương trình khác như biến nhân vật vì vậy tôi không thể làm điều này v1<- quote(Sepal.Length) mà dường như công việc.

+9

Điều này có thể giúp bạn đi đúng hướng: 'dt [, tổng (get (v1), na.rm = TRUE), theo = v2]' hoặc đề xuất phương pháp thay thế nếu bạn linh hoạt. – flodel

+0

Thx. Nó hoạt động, chuyện gì đã xảy ra? Hàm nhận đối tượng có tên v1. Chức năng thay thế đã làm gì với biểu thức này? Nó không làm bất cứ điều gì và cố gắng thay thế v1 với giá trị ký tự "Sepal.Length"? – user1157129

Trả lời

20

Một thay thế cho flodel của câu trả lời trong các ý kiến ​​có thể là

e <- parse(text = paste0("sum(", v1, ", na.rm = TRUE)")) 

b <- parse(text = v2) 

rDT2 <- dt[, eval(e), by = eval(b)] 

#    b V1 
# [1,]  setosa 250.3 
# [2,] versicolor 296.8 
# [3,] virginica 329.4 

EDIT:

Và để đưa điều này vào một chức năng,

getResult <- function(dt, expr, gby){ 
    return(dt[, eval(expr), by = eval(gby)]) 
} 

(dtR <- getResult(dt = dt, expr = e, gby = b)) 
# gives the same result as above 


EDIT từ Matthew : Có một lý do tại sao các phương pháp paste0eval \ quote cũng có thể nhanh hơn get trong một số trường hợp. Một trong những lý do nhóm có thể nhanh chóng là data.table kiểm tra j để xem cột nào sử dụng, sau đó chỉ đặt các cột được sử dụng (Câu hỏi thường gặp 1.12 và 3.1). Nó sử dụng base::all.vars(j) để làm điều đó. Khi sử dụng get() trong j cột đang được sử dụng là ẩn từ all.varsdata.table rơi trở lại Subsetting tất cả các cột chỉ trong trường hợp biểu thức j cần họ (giống như khi biểu tượng .SD được sử dụng trong j, mà .SDcols đã được bổ sung để giải quyết) . Nếu tất cả các cột được sử dụng dù sao thì nó không tạo sự khác biệt, nhưng nếu DT là 1e7x100 thì một nhóm j=sum(V1) phải nhanh hơn nhiều so với nhóm j=sum(get("V1")) vì lý do đó. Ít nhất, đó là những gì đáng lẽ phải xảy ra, và nếu không thì đó có thể là một lỗi. Mặt khác, nếu nhiều truy vấn đang được xây dựng động và lặp lại thì thời gian tới paste0parse có thể xuất hiện trong đó. Tất cả phụ thuộc thực sự. Thiết lập verbose=TRUE sẽ in ra một thông báo về các cột đã được phát hiện như được sử dụng bởi j, do đó có thể được kiểm tra.

+0

Cảm ơn, quay trở lại câu hỏi ban đầu, làm cách nào để làm điều này với giải pháp getResult <- function (dt, expr, gby) { in (dt [, eval (expr), by = eval (b)]) } v1 <- "Sepal.Length" v2 <- "Loài" e <- phân tích cú pháp (văn bản = dán ("tổng (", v1, ", na.rm = TRUE)")) b <- phân tích cú pháp (văn bản = v2) # rDT2 <- dt [, eval (e), by = eval (b)] dtR <- getResult (dt, e, b) – user1157129

+0

@ user1157129, Xin lỗi vì thiếu sót chức năng như được yêu cầu trong câu hỏi của bạn. Vui lòng xem chỉnh sửa cho đề xuất. – BenBarnes

+0

Xin lỗi Ben, nó không hoạt động, tôi có làm gì đó không? getResult <- function (dt, expr, gby) { trả về (dt [, eval (expr), by = eval (gby)]) } dt <- data.table (iris) v1 <- "Sepal.Length" v2 <- "Loài" e <- phân tích cú pháp (văn bản = dán ("sum (", v1, ", na.rm = TRUE)")) b <- parse (văn bản = v2) dtR <- getResult (dt = dt, expr = e, gby = b) – user1157129

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