2013-01-16 91 views
1

我想創建一個函數,其功能與「ggplot2aes()函數一樣。我卑微的嘗試失敗,並出現「未找到對象」錯誤:函數返回一個唯美映射

library(ggplot2) 

data <- data.frame(a=1:5, b=1:5) 

# Works 
ggplot(data) + geom_point() + aes(x=a, y=b) 

my.aes <- function(x, y) { aes(x=x, y=y) } 
# Fails with "Error in eval(expr, envir, enclos) : object 'x' not found" 
ggplot(data) + geom_point() + my.aes(x=a, y=b) 

什麼是落實my.aes()正確的方法是什麼?這是爲了封裝和代碼重用。

也許這是相關的,我只是還沒有看到如何: How to write an R function that evaluates an expression within a data-frame

+2

不知道你在這裏之後,但是http://docs.ggplot2.org/current/aes_string.html? –

+0

@RomanLuštrik:謝謝你,沒有意識到這一點。小心將其轉換爲答案? – krlmlr

回答

3

類型aes無任何括號或參數,看看它在做什麼:

function (x, y, ...) 
{ 
    aes <- structure(as.list(match.call()[-1]), class = "uneval") 
    rename_aes(aes) 
} 

它需要它的參數的名稱不加評估了。它基本上保存了以後的名稱,以便它可以在你試圖繪製的數據框的上下文中評估它們(這就是爲什麼你的錯誤信息是抱怨eval)。因此,當您在您的ggplot建設中包含my.aes(x=a, y=b)時,它正在尋找xdata - 因爲x沒有在aes(x=x, y=y)評估。

考慮在aes發生了什麼事情的另一種方法是一樣的東西

my.aes <- function(x, y) { 
    ans <- list(x = substitute(x), y = substitute(y)) 
    class(ans) <- "uneval" 
    ans 
} 

應在例如工作之上,但看到plyr::.的說明(使用相同match.call()[-1]範式爲aes):

Similar tricks can be performed with substitute, but when functions can be called in multiple ways it becomes increasingly tricky to ensure that the values are extracted from the correct frame. Substitute tricks also make it difficult to program against the functions that use them, while the quoted class provides as.quoted.character to convert strings to the appropriate data structure.

如果你想my.aes調用aes本身,或許是這樣的:

aes_string功能
my.aes <- function(x,y) { 
    do.call(aes, as.list(match.call()[-1])) 
} 

例子指出了羅馬Luštrik:

my.aes <- function(x,y) { 
    aes_string(x = x, y = y) 
} 

,但你需要你的電話改變my.aes("a", "b")在這種情況下。

+0

謝謝你的解釋。你的建議基本上意味着重新實現'aes',我寧願避免。有沒有辦法只使用'aes'來實現'my.aes'? (稍後,還會有'my.geom_text',也許還有其他...) – krlmlr

+0

對於我而言,如果不瞭解更多關於'my.aes'的行爲與'aes的區別' - 以你爲例,他們做同樣的事情。如果你願意寫my.aes(「a」,「b」)而不是my.aes(a,b),羅馬的'aes_string'建議將會起作用,但我不打算把它放在我的答案中這是他的想法。 – user1935457

+0

隨意在您的回答中包含這一點,我不認爲這個想法。就像外星人一樣,它就在外面! :) –