2013-08-20 36 views
6

Tôi đang viết một số chức năng để thực hiện các tác vụ lặp lại, nhưng tôi đang cố gắng giảm thiểu số lần tôi tải dữ liệu. Về cơ bản tôi có một chức năng mà có một số thông tin và làm cho một cốt truyện. Sau đó, tôi có một chức năng thứ hai sẽ lặp qua và xuất nhiều lô thành một tệp .pdf. Trong cả hai chức năng tôi có dòng mã sau đây:Lựa chọn môi trường chức năng lồng nhau

if(load.dat) load("myworkspace.RData") 

nơi load.dat là một logic và dữ liệu mình cần được lưu trữ trong myworkspace.RData. Khi tôi gọi hàm wrapper lặp lại và xuất ra nhiều ô, tôi không muốn tải lại vùng làm việc trong mọi cuộc gọi đến hàm bên trong. Tôi nghĩ rằng tôi chỉ có thể tải không gian làm việc một lần trong chức năng wrapper, sau đó chức năng bên trong có thể truy cập dữ liệu đó, nhưng tôi có một lỗi nói khác. Vì vậy, sự hiểu biết của tôi là khi một hàm không thể tìm thấy biến trong môi trường cục bộ của nó (được tạo khi hàm được gọi), hàm sẽ xem xét môi trường cha mẹ cho biến đó.

Tôi giả định môi trường mẹ cho cuộc gọi hàm bên trong sẽ là cuộc gọi hàm bên ngoài. Rõ ràng đây là không đúng:

func1 <- function(...){ 
    print(var1) 
} 

func2 <- function(...){ 
    var1 <- "hello" 
    func1(...) 
} 

> func2() 
Error in print(var1) : object 'var1' not found 

Sau khi đọc rất nhiều câu hỏi, hướng dẫn ngôn ngữ, và this bài đăng blog thực sự hữu ích, tôi đã đưa ra như sau:

var1 <- "hello" 
save(list="var1",file="test.RData") 
rm(var1) 

func3 <- function(...){ 
    attach("test.RData") 
    func1(...) 
    detach("file:test.RData") 
} 

> func3() 
[1] "hello" 

Có cách nào tốt hơn để làm điều này? Tại sao không func1 tìm các biến không xác định trong môi trường cục bộ được tạo bởi func2, khi đó là func2 được gọi là func1?

Lưu ý: Tôi không biết cách đặt tên cho câu hỏi này. Nếu bất cứ ai có đề xuất tốt hơn, tôi sẽ thay đổi nó và chỉnh sửa dòng này.

đóng cửa
+2

Phạm vi từ vựng có nghĩa là chức năng sẽ xem xét cho các ký hiệu không xác định trong môi trường mẹ của nó, mà không nhất thiết phải là môi trường gọi. Kiểm tra điều này cũng: https://github.com/hadley/devtools/wiki/Environments –

+0

@ Ferdinand.kraft Cảm ơn bạn đã liên kết. Tôi sẽ làm việc thông qua chiều nay. – dayne

+0

Nếu dữ liệu của bạn ở dạng dataframes, bạn có thể sử dụng gói 'data.table' và chuyển các bảng của bạn thành đối số cho' func1' bên trong 'func3'. Gói này hoạt động theo tham chiếu và không tạo các bản sao dữ liệu không mong muốn của bạn. –

Trả lời

7

Để minh họa Phạm vi từ vựng, hãy xem xét những điều sau đây:

Đầu tiên chúng ta hãy tạo ra một môi trường sandbox, duy nhất để tránh các R_GlobalEnv oh-so-chung:

sandbox <-new.env() 

Bây giờ chúng tôi đặt hai hàm bên trong nó: f, tìm kiếm một biến có tên là x; và g, trong đó xác định một địa phương x và gọi f:

sandbox$f <- function() 
{ 
    value <- if(exists("x")) x else "not found." 
    cat("This is function f looking for symbol x:", value, "\n") 
} 

sandbox$g <- function() 
{ 
    x <- 123 
    cat("This is function g. ") 
    f() 
} 

technicality: vào định nghĩa chức năng trong giao diện điều khiển gây ra thì phải có môi trường kèm theo thiết lập để R_GlobalEnv, vì vậy chúng tôi tự buộc các thùng của fg để phù hợp với môi trường nơi chúng "thuộc về":

environment(sandbox$f) <- sandbox 
environment(sandbox$g) <- sandbox 

Gọi g. Biến địa phương x=123 không được tìm thấy bởi f:

> sandbox$g() 
This is function g. This is function f looking for symbol x: not found. 

Bây giờ chúng ta tạo ra một x trong môi trường toàn cầu và gọi g.Chức năng f sẽ tìm kiếm x đầu tiên trong sandbox, và sau đó trong công ty mẹ của sandbox, mà sẽ xảy ra là R_GlobalEnv:

> x <- 456 
> sandbox$g() 
This is function g. This is function f looking for symbol x: 456 

Chỉ cần để kiểm tra xem f tìm kiếm x đầu tiên trong bao vây của nó, chúng ta có thể đặt một x ở đó và gọi g:

> sandbox$x <- 789 
> sandbox$g() 
This is function g. This is function f looking for symbol x: 789 

Kết luận: tra cứu biểu tượng trong R sau chuỗi của môi trường bao quanh, không các khung đánh giá được tạo ra trong thực hiện các chức năng lồng nhau cuộc gọi.

EDIT: Chỉ cần thêm một liên kết đến this very interesting answer from Martin Morgan on the related subject of parent.frame() vs parent.env()

+0

Đây là minh họa tốt nhất mà tôi đã thấy. Cảm ơn bạn rất nhiều! Tôi đã không thực sự hiểu sự khác biệt trong môi trường và khung hình. – dayne

2

Bạn có thể sử dụng:

f2 <- function(...){ 
    f1 <- function(...){ 
    print(var1) 
    } 
    var1 <- "hello" 
    f1(...) 
} 
f2() 
+0

Phải, nhưng tôi cần có khả năng sử dụng chức năng bên trong như một chức năng độc lập. Tôi không muốn phải xác định lại hàm bên trong mỗi khi tôi gọi hàm bên ngoài (không kể đến một loạt mã). – dayne

+0

Sau đó, các thiết lập sạch trong quan điểm của tôi: đặt tất cả dữ liệu của bạn trong một danh sách (my_data), sau đó cung cấp cho nó như là đối số cho chức năng của bạn. Bên trong hàm bạn có thể sử dụng với (my_data, {}) để tránh nhập thêm. –

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