2010-08-09 61 views
2

的d函數在R中,我想調用應用於巨大的data.frame,並將值寫回到其他數據框的特定位置。在apply()中分配變量 - 使用<< -

但是,使用'< < - '僅適用於從全局環境調用apply函數的情況。據我所知,'< < - '搜索變量的parent.env()。爲什麼在bar()而不是bar的環境中調用該函數的父級環境? 謝謝!

do_write_foo1 <- function(x) { 
    cat("parent environment of function called in bar(): ") 
    print(parent.env(environment())) 
    foo1[x['a']] <<- 100+x['a'] 
} 
do_write_foo2 <- function(x) { 
    foo2[x['a']] <<- 100+x['a'] 
} 

bar <- function() { 
    cat("bar environment: ") 
    print(environment()) 
    foo1 <- 1:10 
    apply(data.frame(a=1:10),1,do_write_foo1) 
    foo1 
} 

# this does not work:  
bar() 
# bar environment: <environment: 0x3bb6278> 
# parent environment of function called in bar(): <environment: R_GlobalEnv> 
# Error in foo1[x["a"]] <<- 100 + x["a"] : object 'foo1' not found 


# this works: 
foo2<-1:10 
apply(data.frame(a=1:10),1,do_write_foo2) 
foo2 
# [1] 101 102 103 104 105 106 107 108 109 110 
+0

請注意,在第一次運行時,bar()沒有找到foo。嘗試在rm(foo)之後運行它。這意味着它不是在函數內搜索。爲什麼? – 2010-08-09 12:53:29

+0

感謝您的注意,這是我犯的一個錯誤,並將其更改爲具有兩個不同的變量名稱。 找不到變量的原因是bar-called函數的parent.env()不是bar的環境。但我也不知道爲什麼會這樣。 – 2010-08-09 13:05:36

+0

這非常違背R編程的精神。通常情況下最好避免使用非局部副作用的功能。 – hadley 2010-08-13 03:09:17

回答

2

由於我在包名稱空間內,我必須使用與Etiennebr不同的解決方案。我認爲它很優雅:將bar的環境分配給do_write_foo1。

do_write_foo1 <- function(x) { 
    cat("parent environment of function called in bar(): ") 
    print(parent.env(environment())) 
    foo1[x['a']] <<- 100+x['a'] 
} 

bar <- function() { 
    cat("bar environment: ") 
    print(environment()) 
    foo1 <- 1:10 
    environment(do_write_foo1) <- environment() 
    apply(data.frame(a=1:10),1,do_write_foo1) 
    foo1 
} 

# now it works:  
bar() 
+0

給出你的constaints,這是一個不錯的解決方案。但是,我會認爲這些環境就像被稱爲的俄羅斯套娃娃一樣。 << - 似乎不是這種情況。這超出了我的理解。 – 2010-08-09 14:44:20

1

看來R不是在函數內部搜索(我不明白爲什麼),所以你需要將值賦給global.env foo。

bar <- function() { 
    foo <<-1:10 
    apply(data.frame(a=1:10),1,do_write_foo) 
    foo 
} 
bar() 
# [1] 101 102 103 104 105 106 107 108 109 110 
+0

謝謝,這解決了這個問題。不幸的是,這隻會導致下一個問題: .local(filename,type,...)中的錯誤: 無法更改'spectrumTitles'的鎖定綁定值 (它是變量我想分配給的頻譜標題)。 我正在開發一個軟件包,並且在軟件包內可能無法使用<< - 。 – 2010-08-09 13:18:29

+0

也許你可以看看使用類似 assign(「foo」,foo,loadNamespace(「YourPackage」)) – 2010-08-10 12:55:41

相關問題