40

これは、R コードをデバッグする私の能力に本当に挑戦しました。

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が役立つかもしれないと思いましたが、今日は十分に頭を悩ませたので、手を挙げて助けを求める時が来ました。

4

5 に答える 5

23

この質問に対する今日の解決策は、 にするsummarizeことhere(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 に追加され、現在のコンテキストをキャプチャします。

于 2013-06-27T18:38:26.923 に答える
14

do.callとを組み合わせてこれを行うと、がまだ表示callされている環境で呼び出しを構築できます。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
于 2011-08-05T14:26:29.153 に答える
9

またはまたは何かと組み合わせるddplyと、このような問題に遭遇することがあります。さまざまな環境をナビゲートする際の内外を推測するほど賢くないので、単に使用せず、代わりに独自の匿名関数を使用することで問題を回避する傾向があります。summarizetransformsummarize

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)

ddply明らかに、この作業を「手動で」行うにはコストがかかりますが、多くの場合、とを組み合わせることから生じる評価の問題に対処するという頭痛の種を回避できますsummarize。もちろん、ハドリーが解決策を提示しないと言っているわけではありません...

于 2011-08-05T13:47:21.863 に答える
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
于 2011-08-05T15:28:50.683 に答える
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)

evalparent.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)

以前の環境から my.parse を引き出すために使用getすることで、さらに近づけることができますが、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()戦略のすべてが失敗した理由です。

于 2011-08-05T11:00:48.603 に答える