13

これは非常に複雑な質問のように思えるかもしれませんが、しばらくの間、私は少し頭がおかしくなります。それは好奇心のためでもあります。なぜなら、私はすでに必要なことをする方法を持っているので、それほど重要ではありません。

Rでは、ユーザーが入力したすべての引数と値を含む名前付きリストオブジェクトを返す関数が必要です。このために私はこのコードを作成しました(おもちゃの例):

foo <- function(a=1, b=5, h='coconut') {
    frm <- formals(foo)
    parms <- frm
    for (i in 1:length(frm))
        parms[[i]] <- get(names(frm)[i])
    return(parms)
}

だからこれが尋ねられたとき:

> foo(b=0)

$a
[1] 1

$b
[1] 0

$h
[1] "coconut"

この結果は完璧です。問題は、私lapplyが同じ目標を使用しようとすると、もう少し効率的(かつエレガント)になるように、私が望むように機能しないということです:

foo <- function(a=1, b=5, h='coconut') {
    frm <- formals(foo)
    parms <- lapply(names(frm), get)
    names(parms) <- names(frm)
    return(parms)
}

get問題は明らかに、最初の引数(文字列、変数の名前)を評価する環境にあります。これは私がエラーメッセージから部分的に知っています:

> foo(b=0)
Error in FUN(c("a", "b", "h")[[1L]], ...) : object 'a' not found

また、.GlobalEnv環境内に正しい名前のオブジェクトがある場合、fooは代わりにそれらの値を返します。

> a <- 100
> b <- -1
> h <- 'wallnut'
> foo(b=0)
$a
[1] 100

$b
[1] -1

$h
[1] "wallnut"

明らかに、getデフォルトでで評価されるように、現在の関数のオブジェクトではなく、環境parent.frame()内のオブジェクトを検索します。.GlobalEnvこれは、関数の最初のバージョンでは発生しないため、奇妙です。

適切な環境で評価する関数を作成するために多くのオプションを試しgetましたが、正しく実行できませんでした(オプションとして試しましたpos=-2,0,1,2envir=NULL

特にこの「奇妙な」場合に、誰かが私より少し環境について知っているなら、私はこれを解決する方法を知りたいです。

御時間ありがとうございます、

ファン

4

3 に答える 3

11

2013-08-05の編集

sapply()の代わりにを使用するとlapply()、これが大幅に簡略化されます。

foo4 <- function(a=1, b=5, h='coconut') {
    frm <- formals(sys.function())
    sapply(names(frm), get, envir=sys.frame(sys.parent(0)), simplify=FALSE)
}
foo4(b=0, h='mango')

ただし、これは、よりエレガントなソリューションがないsapply() lapply()、よりエレガントなソリューションである可能性があります。

foo5 <- function(a=1, b=5, h='coconut') {
    modifyList(formals(sys.function()), as.list(match.call())[-1])
}
foo5(b=0, h='mango')

元の投稿(2011-11-04)

少しキャストした後、これが最良の解決策のように見えます。

foo <- function(a=1, b=5, h='coconut') {
    frm <- formals(foo)
    parms <- lapply(names(frm), get, envir=sys.frame(sys.parent(0)))
    names(parms) <- names(frm)
    return(parms)
}
foo(b=0, h='mango')
# $a
# [1] 1

# $b
# [1] 0

# $h
# [1] "mango"

lapplyここでは、構築する呼び出しをスコープ/評価する方法について、微妙なことがいくつか行われています。詳細はへの呼び出しに隠されていますが.Internal(lapply(X, FUN))、好みのために、これら2つの呼び出しを比較してください。

# With function matched by match.fun, search in sys.parent(0)
foo2 <- function(a=1, h='coconut') {
    lapply(names(formals()), 
           get, envir = sys.parent(0))
}

# With anonymous function, search in sys.parent(2)    
foo3 <- function(a=1, h='coconut') {
    lapply(names(formals()), 
           FUN = function(X) get(X, envir = sys.parent(2)))
}

foo4(a=0, h='mango')
foo5(a=0, h='mango')
于 2011-11-04T23:41:29.277 に答える
7

現在の環境をリストに変換するだけです。

foo <- function(a=1, b=5, h='coconut') {
  as.list(environment())
}
foo(a = 0, h = 'mango')
于 2013-08-07T01:53:12.887 に答える
1

これは、上記の@Josh O'Brienのソリューションを使用sapplyして、結果のリストに正しい名前を自動的に割り当てることで適応されます(1行のコードを節約します)。

foo <- function(a=1, b=5, h='coconut') {
    frm <- formals(foo)
    parms <- sapply(names(frm), get, envir=sys.frame(sys.parent(-1)), simplify=FALSE)
    return(parms)
}
于 2011-11-04T23:35:08.417 に答える