7

自己記述関数内から使用しようとしましたが、acast に送信したデータが見つからないという問題がありましacastた。reshape2

ここに私のデータがあります:

library("reshape2")
x <- data.frame(1:3, rnorm(3), rnorm(3), rnorm(3))    
colnames(x) <- c("id", "var1", "var2", "var3")
y <-melt(x, id = "id", measure = c("var1", "var2", "var3"))

y次に、次のようになります。

  id variable      value
1  1     var1  0.1560812
2  2     var1  1.0343844
3  3     var1 -1.4157728
4  1     var2  0.8808935
5  2     var2  0.1719239
6  3     var2  0.6723758
7  1     var3 -0.7589631
8  2     var3  1.1325995
9  3     var3 -1.5744876

今、私はそれを介してキャストすることができますacast:

> acast(y,y[,1] ~ y[,2])
        var1      var2       var3
1  0.1560812 0.8808935 -0.7589631
2  1.0343844 0.1719239  1.1325995
3 -1.4157728 0.6723758 -1.5744876

ただし、同じことを行う必要がある小さなラッパーを作成するacastと、愚かなエラーメッセージが表示されます。

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    out <- acast(dat, dat[,v1] ~ dat[,v2])
    return(out)
}

wrap.acast(y)

Error in eval(expr, envir, enclos) : object 'dat' not found

この問題は明らかに、環境やグローバル/ローカル変数などに関連しています。datグローバル環境で宣言した後に他のエラーメッセージが表示されるため(つまり、グローバルv1v2ない限り見つからない)。

関数外で変数を宣言する必要なく、関数内で resahpe (特に acast) を使用したいと思います。トリックは何ですか?

ありがとう。

4

4 に答える 4

7

数式指定を使用する代わりに、文字指定を使用します。

acast(y, list(names(y)[1], names(y)[2]))
于 2010-09-22T13:32:40.153 に答える
4

1 つの問題は、R の数式表記を悪用していることです。次のようなことを行うべきではありません。

> acast(y, y[,1] ~ y[,2])
        var1       var2         var3
1  2.1726117  0.6107264  0.291446236
2  0.4755095 -0.9340976 -0.443291873
3 -0.7099464 -1.2536334  0.001105352

データオブジェクトが提供されている場合、「y」ビットは冗長であるためです。式の中で y の変数を名前で直接参照すると、問題なく動作します。

> acast(y, id ~ variable)
        var1       var2         var3
1  2.1726117  0.6107264  0.291446236
2  0.4755095 -0.9340976 -0.443291873
3 -0.7099464 -1.2536334  0.001105352

この 2 番目のバージョンでは、コードがはるかに読みやすくなっています。

Jorisが指摘しているように、ラッパーを使用して必要なことを行うには、をacast使用して正しい式を生成する必要があり、Hadleyのソリューションははるかに簡単です. namesしたがって、私のポイントは、R で式の仕様を使用する方法に注意することです。式を適切に使用すると、長期的には多くの問題を回避できます (特にこの特定の問題ではありません)。

于 2010-09-22T14:08:22.213 に答える
2

訂正: 問題は、dat が見つからないことではなく、指定された数式で dat[,v1] と dat[,v2] が見つからないことです。Acast は式の型の引数を取り、その引数はデータ フレームの周りに作成された一時的な環境で評価されます。その環境内では、関数が別のオブジェクトにラップされている場合、「dat」オブジェクトは見つかりません。

これがグローバルでどのように機能し、ラップされたときに機能しないかについては完全には理解していませんが、acast 式をフィードすると、関数内でも機能します。

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    x1 <- names(dat)[v1]
    x2 <- names(dat)[v2]
    form <- as.formula(paste(x1,"~",x2))
    out <- acast(dat,form)
    return(out)
}

あなたのおもちゃのデータを使用して:

> wrap.acast(y)
        var1      var2       var3
1 0.04095337 0.4044572 -0.4532233
2 1.23905358 1.2493187  0.7083557
3 0.72798307 0.7868746  1.7144811
于 2010-09-22T12:51:29.120 に答える
-2

スーパー代入を使用して問題を解決するかなり洗練されていない方法を見つけました ( <<-)。
関数を次のように変更すると、うまくいきます。しかし、残っているグローバル変数を作成するので、かなり醜いです。

wrap.acast <- function(dat, v1 = 1, v2 = 2) {
    dat <<- dat
    v1 <<- v1
    v2 <<- v2
    out <- acast(dat, dat[,v1] ~ dat[,v2])
    return(out)
}

私はまだ他の(目詰まりの少ない)ソリューションに非常に興味があります.

関数を実行する前に:

> ls()
[1] "wrap.acast" "x"          "y"     

関数を実行した後:

> ls()
[1] "dat"        "v1"         "v2"         "wrap.acast" "x"         
[6] "y" 
于 2010-09-22T12:52:21.310 に答える