2013-08-20 22 views
6

Tekrarlanan görevler yapmak için bazı işlevler yazıyorum, ancak veriyi yüklediğim süreyi en aza indirmeye çalışıyorum. Temel olarak bazı bilgileri alan ve bir çizim yapan bir fonksiyonum var. Daha sonra, bir çok pini bir .pdf'ye gönderecek ve çıkacak ikinci bir işlevim var. her iki işlev I kod aşağıdaki satırı vardır: load.dat mantıklı ve ihtiyacım veri myworkspace.RData saklanır olanİç içe geçmiş işlev ortamı seçimi

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

. Dönen ve birden fazla parsel çıkaran sarıcı işlevini çağırdığımda, iç işleve yapılan her çağrıda çalışma alanını yeniden yüklemek istemiyorum. Çalışma alanını bir kez sarmalayıcı işlevine yükleyebildiğimi sandım, sonra içsel işlev bu verilere erişebiliyordu, fakat aksi halde bir hata oluştu.

Bu nedenle, bir işlev değişkeni yerel ortamdaki değişkende bulamadığında (işlev çağrıldığında oluşturulduğunda), işlev değişkenin ana ortamına bakacaktır.

Ana ortamın iç işlev çağrısının dış işlev çağrısı olacağını varsaydım. Açıkçası bu doğru değildir:

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

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

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

çok sayıda soru, dil kılavuzu ve this gerçekten yararlı blog yazısı okuduktan sonra geldi şu:

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

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

> func3() 
[1] "hello" 

yapmak için daha iyi bir yolu var mı bu? Neden func1, func2 tarafından oluşturulan yerel ortamda tanımlanmamış değişkenleri aramıyor, func1 adı verilen func2 iken?

Not: Bu soruyu nasıl adlandıracağımı bilmiyordum. Daha iyi öneriler varsa, bunu değiştirip bu satırı düzenlerim.

+2

Sözcük Kapsama alma bir bağlantı ekleyerek fonksiyonu mutlaka çağıran ortam değil üst ortamında, tanımsız sembollerin arayacaktır anlamına gelir. Bunu da kontrol edin: https://github.com/hadley/devtools/wiki/Environments –

+0

@ Ferdinand.kraft Bağlantı için teşekkürler. Bu öğleden sonra çalışacağım. – dayne

+0

Verileriniz veri çerçeve biçimindeyse, 'data.table' paketini kullanabilir ve tablolarınızı func1' func3' içinde bir argüman olarak iletebilirsiniz. Bu paket referans olarak çalışır ve verilerinizin istenmeyen kopyalarını oluşturmaz. –

cevap

7

, sözcük kapsam belirleme göstermek aşağıdakileri dikkate için:

:

İlk tek önlemek için, oh-so-ortak R_GlobalEnv bir test ortamı yaratalım

sandbox <-new.env() 

Şimdi iki işlevi yerine koyarız: f, x adında bir değişken arar; Yerel bir x tanımlar ve çağırır ve g, 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() 
} 

Teknik Özellikler: konsolda işlev tanımları giren R_GlobalEnv ayarlı kapsayan ortamına sahip sonra neden, bu yüzden elle maç için f ve g duvarla çevrili zorlamak "ait oldukları" çevre:

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

Arama g. Yerel değişken x=123f da bulunmayacak:

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

Şimdi küresel ortamda bir x oluşturup g arayın.fonksiyon f R_GlobalEnv olur sandbox ebeveyn, daha sonra ilk sanal alanda x arar ve olacaktır:
> x <- 456 
> sandbox$g() 
This is function g. This is function f looking for symbol x: 456 

Sadece f kendi muhafazaya için x ilk görünüyor kontrol etmek, bir x koyabilirsiniz g vardır ve çağırır:

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

Sonuç: R simgesi arama iç içe işlevin yürütülmesi sırasında oluşturulan kapama ortamlarda zincirini değil değerlendirme çerçeveleri aşağıdaki çağırır.

DÜZENLEME: Sadece this very interesting answer from Martin Morgan on the related subject of parent.frame() vs parent.env()

+0

Bu, gördüğüm en iyi örnek. Çok teşekkür ederim! Ortamlarda ve çerçevelerde farkı anlamıyordum. – dayne

2

Şunları kullanabilirsiniz kapanışları:

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

Doğru, ama iç işlevi bağımsız bir işlev olarak kullanabilmem gerekiyor. Dış fonksiyonu çağırdığım her seferinde içsel fonksiyonu yeniden tanımlamak istemedim (kod demetini çoğaltmaktan bahsetme). – dayne

+0

O zaman en temiz ayar benim görüşüme göre: Tüm verilerinizi bir listeye (my_data) koyup fonksiyonunuza bir argüman olarak verin. Ekstra yazmayı önlemek için işlevin içinde (my_data, {}) ile birlikte kullanabilirsiniz. –

İlgili konular