2017-07-03 131 views
1

說我們有這個玩具數據ggplot:無法通過ylim參數的函數

temp <- data.frame(A=1:6, gr=c("A","A","A","B","B","B")) 

我可以輕鬆地創建一個情節一樣

lev <- c("A", "B") 
ggplot()+geom_point(data=temp,aes(x=A, y=gr))+ylim(lev) 

我得到這個 enter image description here

但我想將其轉換爲函數以便輕鬆更改輸入參數

myplot <- function(lev=lev) {ggplot()+geom_point(data=temp,aes(x=A, y=gr))+ylim(lev)} 

但是當我運行

lev <- c("B","A") 
myplot() 

我得到這個錯誤:

Error in limits(c(...), "y") : promise already under evaluation: recursive default argument reference or earlier problems?

我試着轉換ylim的因素,使用eval,但它也不管用。

我試過參數化其他東西,如輸入數據集,他們工作得很好,但我不明白爲什麼ylim沒有。

有這充分說明有關相關問題與AES參數
Pass function argument to ggplot label

一個問題,但它的解決方案使用aes_string,在這裏並不適用。

回答

3

更改你如何定義你的函數:

myplot <- function(lev) { #I think setting lev in the definition is causing problems 
    ggplot(data=temp, aes(x=A, y=gr))+ 
    geom_point()+ 
    ylim(lev) 
} 

然後建立一個新的變量集合級別:

args=c("B", "A") #can reorder these however you want 
myplot(lev=args) 
+0

我使用lev = lev,因爲我想要一個默認參數。但這很奇怪,因爲如果我在定義 – skan

2

你不調用帶有參數的功能!

myplot() 

因爲您沒有給出它的參數而引發錯誤。 如果你稱它爲你應該稱之爲的(由你自己的定義來定義),它就會起作用。

myplot(lev) 

編輯:你可能想與lev設置參數lev的默認值?據我瞭解,由於R評估函數參數的方式會導致錯誤。我沒有在這個短時間內找到任何進一步的信息,所以我很樂意看到更深入的答案。 您可以直接設置的默認值一樣,

myplot <- function(lev = c("A", "B)) {...} 

那麼你也可以打電話給你的功能,無需爭論,即myplot()會工作。

+0

中使用myplot(temp = temp)時我沒有相同的問題,我使用lev = lev,因爲我想要一個默認參數。但是這很奇怪,因爲如果我在定義 – skan

+0

中使用myplot(temp = temp)時我沒有同樣的問題,我現在還沒有真正理解它(我已經很晚了,而且我再也想不到了),但是它肯定要做的事情是你在你的函數外定義了lev。這就是爲什麼當你將參數重命名爲'temp'時你沒有問題。請參閱https://stackoverflow.com/questions/14982223/an-error-i-cant-understand-promise-already-under-evaluation,並在響應中鏈接頁面和https://cran.r-project.org/ doc/manuals/r-release/R-lang.html#參數評估。有評估框架,呼叫環境等。對不起,我不能解釋它 – friep

+0

我預計名稱不會衝突,因爲一個是本地和另一個全球 – skan

0

我發現奇怪的只是用不同於輸入數據的名稱調用函數的參數。

temp <- data.frame(A=1:6, gr=c("A","A","A","B","B","B")) 
mylev <- c("A", "B") 

myplot <- function(lev=mylev) {ggplot()+geom_point(data=temp,aes(x=A, y=gr))+ylim(lev)} 

myplot()工作

這樣我可以有指向特定定義的默認參數。

PD: 仍然無法正常工作。真奇怪。 你第一次運行它的作品。 但如果我再次運行它,我得到這個錯誤:

Error: length(lims) == 2 is not TRUE