2013-10-02 21 views
17

Tôi nhận thấy rằng một vài gói cho phép bạn chuyển các tên biểu tượng có thể không hợp lệ trong ngữ cảnh mà hàm được gọi. Tôi tự hỏi làm thế nào điều này hoạt động và làm thế nào tôi có thể sử dụng nó trong mã của riêng tôi?Chuyển tên biến thành hàm trong R

Dưới đây là một ví dụ với ggplot2:

a <- data.frame(x=1:10,y=1:10) 
library(ggplot2) 
qplot(data=a,x=x,y=y) 

xy không tồn tại trong không gian tên của tôi, nhưng ggplot hiểu rằng họ là một phần của khung dữ liệu và trì hoãn việc đánh giá của họ vào một bối cảnh trong đó họ có giá trị. Tôi đã cố gắng làm điều tương tự:

b <- function(data,name) { within(data,print(name)) } 
b(a,x) 

Tuy nhiên, điều này thất bại thảm hại:

Error in print(name) : object 'x' not found 

Tôi đang làm gì sai? Cái này hoạt động ra sao?

Note: đây là không một bản sao của Pass variable name to a function in r

Trả lời

13

Tôi biết rằng đây là một chủ đề lớn hơn, nhưng nó là một trong tôi đã đề cập đến trong quá khứ. Gần đây tôi đã phát hiện ra những gì tôi nghĩ là một cách tiếp cận tốt hơn để truyền các tên biến. Vì vậy, tôi nghĩ rằng tôi sẽ bao gồm nó. Tôi hi vọng điêu nay se giup được ai đo.

a <- data.frame(x = 1:10, y = 1:10) 

b <- function(df, name){ 
    eval(substitute(name), df) 
} 

b(a, x) 
    [1] 1 2 3 4 5 6 7 8 9 10 

Cập nhật Cách tiếp cận này sử dụng đánh giá không chuẩn. Tôi bắt đầu giải thích nhưng nhanh chóng nhận ra rằng Hadley Wickham làm tốt hơn tôi nhiều. Đọc này http://adv-r.had.co.nz/Computing-on-the-language.html

+1

Bạn có thể chi tiết hơn một chút (thêm một vài bình luận) không? Cách tiếp cận này nghe có vẻ thú vị. Lưu ý rằng không có "chủ đề cũ" trên ngăn xếp tràn, thông tin được lưu giữ cho những người như bạn và tôi, những người google câu hỏi của họ. –

+1

@static_rtti Tôi đã cập nhật câu trả lời. HTH –

+1

Đây là một viên ngọc của một câu trả lời, cảm ơn bạn. Nếu nó giúp, thì nếu 'var <- eval (thay thế (var), dữ liệu)' cung cấp cho bạn đối tượng, thì 'var.name <- replace (var)' cung cấp cho bạn tên biến được truyền để sử dụng trong hàm. – drstevok

9

Bạn có thể làm điều này bằng match.call ví dụ:

b <- function(data,name) { 

    ## match.call return a call containing the specified arguments 
    ## and the function name also 
    ## I convert it to a list , from which I remove the first element(-1) 
    ## which is the function name 

    pars <- as.list(match.call()[-1]) 
    data[,as.character(pars$name)] 

} 

b(mtcars,cyl) 
[1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4 

giải thích:

match.call trả về một cuộc gọi trong đó tất cả các đối số được chỉ định là được chỉ định bằng tên đầy đủ của họ.

Vì vậy, đây đầu ra của match.call là 2 biểu tượng:

b <- function(data,name) { 
    str(as.list(match.call()[-1])) ## I am using str to get the type and name 
} 

b(mtcars,cyl) 
List of 2 
$ data: symbol mtcars 
$ name: symbol cyl 

Vì vậy, Sau đó, tôi sử dụng mtcars biểu tượng đầu tiên ansd chuyển đổi thứ hai để một chuỗi:

mtcars[,"cyl"] 

hoặc tương đương với:

eval(pars$data)[,as.character(pars$name)] 
+0

Bạn có thể giải thích một chút về cách hoạt động của nó không? –

+1

@static_rtti Tôi thêm một số lời giải thích. Hy vọng nó là rõ ràng hơn bây giờ. – agstudy

+0

Cảm ơn, giờ đây rõ ràng hơn rất nhiều. Tôi vẫn muốn hiểu tại sao phiên bản của tôi không thành công. –

0

Nếu bạn đặt tên biến giữa dấu ngoặc kép khi bạn gọi hàm, nó hoạt động:

> b <- function(data,name) { within(data,print(name)) } 
> b(a, "x") 
[1] "x" 
    x y 
1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 
8 8 8 
9 9 9 
10 10 10 
Các vấn đề liên quan