2013-04-03 67 views
2

我還是R的新手,並且已經閱讀過以前的類似帖子......我認爲這與r通過承諾而不是價值的事實有關,但是我不是很清楚哪裏錯了這裏..r將值傳遞給內部函數not found

下面的代碼的簡單版本,我也想嘗試:

定義:

data<-data.frame(TYPE=as.integer(runif(20,1,3)),COL1=runif(20,1,100),COL2=runif(20,1,10)) 
RULEA=10 
RULEB=20 

和我跑,如下所示:

f<-function(data,metric="A"){ 
    data<-ddply(data,.(TYPE),transform,SUMCOL1=sum(COL1,na.rm=TRUE),SUMCOL2=sum(COL2,na.rm=TRUE)) 
    data1<-f1(data=data,metric=metric) 
    return(data1) 
} 

f1<-function(data=data,metric="A"){ 
    if(metric=="A"){ 
    RULE<-RULEA 
    data$FACTOR<-data$COL1 
    }else if(metric=="B"){ 
    RULE<-RULEB 
    data$FACTOR<-data$COL1 
    } 
    if(nrow(data!=0)){ 
    x<-subset(data,FACTOR>1) 
    if(nrow(x)!=0){ 
     x<-ddply(x,.(TYPE),mutate,sig=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE) 
    } 
    } 

return(x) 
} 

,如果我如下運行: F(數據,指標= 「A」)

它會給我的結果:

> f(data,metric="A") 
Error in eval(expr, envir, enclos) : object 'RULE' not found 

我不知道爲什麼它不能找到「規則」....? 謝謝你的幫助!

回答

2

這是一種使用data.table的方法,它可能很有用,因爲它避免了這個問題。

請注意,我明確地複製每個函數中的data.tables,以使這些函數的行爲更像一個常規的R函數 - 因此我沒有真正利用data.table內存效率,但它評估的方式爲j很好(它會比ddply更快)。

一般來說,會有更多data.table的方式來做你想做的事情,這個答案並不是真正的嘗試。

f<-function(DT,metric="A"){ 
    ## explicit copy to avoid assignment in global `DT` 
    dd <- copy(DT) 
    ## add sum columns to local copy 
    dd[, c('SUMCOL1', 'SUMCOL2') := lapply(.SD, sum ,na.rm = TRUE),by = 'TYPE', .SDcols = c('COL1','COL2')] 
    # do f1 on dd 
    dd1<-f1(DT = dd,metric=metric) 
    # return results 
    return(dd1) 
} 


f1<-function(DT,metric="A"){ 
    ## explicit copy 
    ddd <- copy(DT) 
    # assign RULE (a bit simpler) 
    RULE <- switch(metric, 'A' = RULEA, 'B' = RULEB) 
    # i FACTOR didn't depend on metric 
    ddd[, FACTOR := COL1] 
    # subset 
    x <- ddd[FACTOR >1, ] 

    x[, sig :=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE ,by = 'TYPE'] 
    return(x) 
} 

f(data.table(data),metric="A") 
+0

謝謝@mnel!我一直是plyr軟件包的忠實粉絲,但它可能是我做出改變的時候...... :) – linp 2013-04-04 13:56:52

2

根據this(舊)討論,這實際上是一個非常具有挑戰性的問題。

正如該討論所指出的那樣,當你到達評估mutate表達式的地步時,ddply已經交給ldply,它已經交給llply。現在mutate必須找出表達式中的所有內容來自哪裏。看起來並不那麼簡單。

一種(可怕的)解決方法是將作業更改爲RULE以使用<<-。哈德利在討論中提到了一個明確的功能,這可能是一個更安全的選擇。

+0

謝謝喬蘭!我剛剛瀏覽了舊帖子,至少我知道問題出在哪裏! :) – linp 2013-04-04 13:53:36

2

也許我失去了一些東西,但如果是的data.framex部分RULE進行評估:

f1<-function(data=data,metric="A"){ 
    if(metric=="A"){ 
    # RULE<-RULEA 
    data$RULE<-RULEA 
    data$FACTOR<-data$COL1 
    }else if(metric=="B"){ 
    # RULE<-RULEB 
    data$RULE<-RULEB 
    data$FACTOR<-data$COL1 
    } 
    if(nrow(data!=0)){ 
    x<-subset(data,FACTOR>1) 
    if(nrow(x)!=0){ 
     x<-ddply(x,.(TYPE),mutate,sig=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE) 
    } 
    } 
    return(x) 
} 

f(data,metric="A") 
# TYPE  COL1  COL2 SUMCOL1 SUMCOL2 RULE FACTOR sig 
# 1  1 43.983597 9.457873 496.6858 60.05813 10 43.983597 TRUE 
# 2  1 60.438590 4.196161 496.6858 60.05813 10 60.438590 TRUE 
# 3  1 20.251421 6.780956 496.6858 60.05813 10 20.251421 TRUE 

我基地的粉絲,所以我可能會重寫你的函數ff1像這樣:

f<-function(data=data,metric='A'){ 
    b<-by(data,data$TYPE, function(x) 
    data.frame(max=max(x$COL1),min=min(x$COL1),SUMCOL1=sum(x$COL1),SUMCOL2=sum(x$COL2))) 
    m<-do.call(rbind,b) 
    m$TYPE<-rownames(m) 
    m$sig<-m$max>(2*m$min) & m$min < switch(metric,A=RULEA,B=RULEB) 
    merge(data,m)[,c(names(data),'SUMCOL1','SUMCOL2','sig')] 
} 


f(data,metric='A') 
+1

是的,把它放入數據框是另一種選擇,但它仍然感覺不是最優的(與理想的變異只是神奇地發現事物相比)。 – joran 2013-04-03 22:25:19

+0

Humm猜測快速更改是將規則放入數據框中...想知道它會減慢大型數據集上的程序的速度,以及實時運行的程序...... – linp 2013-04-04 14:03:45

+0

這是不太可能顯着減慢速度。如果您需要快速完成此操作,請使用'data.table'。 – nograpes 2013-04-04 17:13:13