2011-08-05 38 views
40

這真的對我調試R代碼的能力提出了挑戰。在函數中ddply找不到對象的對象

我想用ddply()相同的功能,適用於按順序命名不同的列;例如。 a,b,c。爲此,我打算重複傳遞列名作爲字符串,並使用eval(parse(text=ColName))來允許函數引用它。我從另一個答案中抓住了這個技巧。

這工作得很好,直到我把ddply()另一個函數內。以下是示例代碼:

# Required packages: 
library(plyr) 

myFunction <- function(x, y){ 
    NewColName = "a" 
    z = ddply(x, y, summarize, 
      Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) 
    ) 
    return(z) 
} 

a = c(1,2,3,4) 
b = c(0,0,1,1) 
c = c(5,6,7,8) 
df = data.frame(a,b,c) 
sv = c("b") 

#This works. 
ColName = "a" 
ddply(df, sv, summarize, 
     Ave = mean(eval(parse(text=ColName)), na.rm=TRUE) 
) 

#This doesn't work 
#Produces error: "Error in parse(text = NewColName) : object 'NewColName' not found" 
myFunction(df,sv) 

#Output in both cases should be 
# b Ave 
#1 0 1.5 
#2 1 3.5 

任何想法? NewColName甚至在函數內定義!

我認爲這個問題的答案loops-to-create-new-variables-in-ddply可能對我有幫助,但是我今天做了足夠的頭撞,現在是時候舉手並尋求幫助。

回答

14

您可以用do.callcall組合做這個來構建呼叫的環境下NewColName仍清晰可見:

myFunction <- function(x,y){ 
NewColName <- "a" 
z <- do.call("ddply",list(x, y, summarize, Ave = call("mean",as.symbol(NewColName),na.rm=TRUE))) 
return(z) 
} 

myFunction(d.f,sv) 
    b Ave 
1 0 1.5 
2 1 3.5 
3

看起來像你有環境問題。全球分配解決了這個問題,但在一個人的靈魂的費用:

library(plyr) 

a = c(1,2,3,4) 
b = c(0,0,1,1) 
c = c(5,6,7,8) 
d.f = data.frame(a,b,c) 
sv = c("b") 

ColName = "a" 
ddply(d.f, sv, summarize, 
     Ave = mean(eval(parse(text=ColName)), na.rm=TRUE) 
) 

myFunction <- function(x, y){ 
    NewColName <<- "a" 
    z = ddply(x, y, summarize, 
      Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) 
    ) 
    return(z) 
} 

myFunction(x=d.f,y=sv) 

eval正在尋找在parent.frame(1)。所以,如果你不是定義之外的MyFunction NewColName它應該工作:

rm(NewColName) 
NewColName <- "a" 
myFunction <- function(x, y){ 

    z = ddply(x, y, summarize, 
      Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) 
    ) 
    return(z) 
} 
myFunction(x=d.f,y=sv) 

通過使用get拔出從早期環境my.parse,我們可以得出非常接近,但還是要過curenv作爲一個全球性的:

myFunction <- function(x, y){ 
    NewColName <- "a" 
    my.parse <- parse(text=NewColName) 
    print(my.parse) 
    curenv <<- environment() 
    print(curenv) 

    z = ddply(x, y, summarize, 
      Ave = mean(eval(get("my.parse" , envir=curenv)), na.rm=TRUE) 
    ) 
    return(z) 
} 

> myFunction(x=d.f,y=sv) 
expression(a) 
<environment: 0x0275a9b4> 
    b Ave 
1 0 1.5 
2 1 3.5 

我懷疑ddply在.GlobalEnv評估已,這就是爲什麼所有的parent.frame()sys.frame()戰略的我試過失敗。

+0

我懷疑該解決方案可能需要@Hadley函數:-) –

+0

嘗試所有這些努力。羣頭猛擊永遠是我的讚賞......我會保持靈魂 –

9

summarizetransform或東西結合時ddply,並且不是足夠聰明可以洞察到瀏覽各種環境的來龍去脈我傾向於通過簡單地不使用summarize到側步的問題,偶爾會碰到這樣的問題,而不是用自己的匿名函數:

myFunction <- function(x, y){ 
    NewColName <- "a" 
    z <- ddply(x, y, .fun = function(xx,col){ 
          c(Ave = mean(xx[,col],na.rm=TRUE))}, 
       NewColName) 
    return(z) 
} 

myFunction(df,sv) 

顯然,是「手動」做這個東西成本,但它往往避免處理那些來自結合ddplysummarize評價問題的頭痛。這並不是說,當然,哈德利將無法與解決方案展示了......

+2

在我修復這個錯誤之前,這是我推薦的解決方法。請注意,您可以在匿名函數中使用'transform'等。 – hadley

+0

@joran我實施了你的解決方案,它爲我工作。我只是好奇爲什麼在ddply中有這個範圍問題?是因爲彙總創建了一個新的數據框,並且不能訪問這個colName? –

+0

@ user3801801它與非標準評估取代函數參數有關。我必須對源代碼進行篩選以提醒自己關於具體問題,但基本上它與R知道如何評估論據(即在當前機箱的環境中,在全球環境中,在某處之間)。 – joran

4

問題在於plyr軟件包本身的代碼。在彙總功能中,有一行eval(substitute(...),.data,parent.frame())。衆所周知,parent.frame()可以做出非常時髦和意想不到的事情。 T

他對@James的解決方案是一個非常好的解決方法,,但如果我記得正確@Hadley自己說之前,plyr包不打算在函數內使用。

對不起,我在這裏是錯的。據瞭解,目前,plyr軟件包在這些情況下會出現問題。

因此,我給你對這個問題的基礎溶液:

myFunction <- function(x, y){ 
    NewColName = "a" 
    z = aggregate(x[NewColName],x[y],mean,na.rm=TRUE) 
    return(z) 
} 
> myFunction(df,sv) 
    b a 
1 0 1.5 
2 1 3.5 
+0

+1用於「避免總結」解決方案並提供問題的實際解釋。 ;) – joran

+0

+1肯定是花時間來解釋parent.frame()問題。看起來很奇怪,一個函數不能在另一個函數中使用,因爲它迫使你編寫連續的代碼。也許@Hadley可以發表評論。 –

+0

我當然從來沒有聲稱,plyr不打算在功能內使用 - 我一直說這是一個錯誤,我目前缺乏理解修復:( – hadley

22

今天的解決這個問題,使summarizehere(summarize)。例如

myFunction <- function(x, y){ 
    NewColName = "a" 
    z = ddply(x, y, here(summarize), 
      Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) 
    ) 
    return(z) 
} 

here(f),2012年12月添加到plyr,捕獲當前上下文。

+0

輝煌!當一起使用lubridate和plyr時,請確保您特別提到plyr :: here()(因爲lubridate不幸在這裏重新定義()) –

+0

更多信息:https://github.com/hadley/plyr/問題/ 3 – Lennert

相關問題