web-dev-qa-db-ja.com

R(置換)で変数の名前を取得する方法は?

いくつかの関数に変数を渡そうとしてスタックし、最後の関数で元の変数の名前を取得したいと思います。しかし、Rの代替関数は、「ローカル」環境でのみ、または1つ上のレベルでのみ検索されたようです。さて、コードで説明しましょう:

fun1 <- function (some_variable) {deparse(substitute(some_variable)}
fun2 <- function (var_pass) { fun1 (var_pass) }
my_var <- c(1,2) # I want to get 'my_var' in the end
fun2 (my_var) # > "var_pass"

さて、fun1にのみ渡される変数の名前を出力しているようです。代替のドキュメントは、env引数を使用してどこを探すことができるかを指定できることを示しています。しかし、。Globalまたは。BaseNamespaceEnvを引数として渡すことで、さらに奇妙な結果が得られました-"some_variable"

答えはenv引数を使用したこの関数にあると思います。それで、それがどのように機能し、どのように必要なものを取得できるかを説明してください。前もって感謝します!

14
EvilAnton

これらの関数にオプションの名前の値を渡すことを検討することをお勧めします。これは、最終結果で名前を何かのラベルとして使用したいように思われるためです。そのため、名前ほど重要なのは変数自体ではありません。あなたができる

fun1 <- function (some_variable, name=deparse(substitute(some_variable))) {
    name
}
fun2 <- function (var_pass, name=deparse(substitute(var_pass))) { 
    fun1 (var_pass, name) 
}
my_var <- c(1,2)

fun2(my_var)
# [1] "my_var"

fun1(my_var)
# [1] "my_var"

このようにして、奇妙な変数名と結果に適切な名前を付けることになった場合、少なくともオプションがあります。また、デフォルトでは、nameパラメーターを必要とせずに必要な処理を実行する必要があります。

16
MrFlick

1つのハック、おそらく最善の方法ではありません:

fun2 <- function (var_pass) { fun1 (deparse(substitute(var_pass))) }

fun1 <- function (some_variable) {(some_variable))}

fun2(my_var)
# "my_var"

そして、その上でgetを実行できます。しかし、Paul Hが示唆しているように、変数を追跡するためのより良い方法があります。

1
Carl Witthoft

私が提案したいもう1つのアプローチは、rlang::enexprを使用することです。主な利点は、元の変数名をパラメーターに含める必要がないことです。欠点は、使用するのが少し難しい式を処理する必要があることです。

> fun1 <- function (some_variable) {
    message("Entering fun1")
    rlang::enexpr(some_variable)
}
> fun2 <- function (var_pass) {
    message("Entering fun2")
    eval(parse(text=paste0("fun1(", rlang::enexpr(var_pass), ")")))
}
> my_var <- c(1, 2)
> fun1(my_var)
#Entering fun1
my_var
> fun2(my_var)
#Entering fun2
#Entering fun1
my_var

ここでの秘訣は、fun2の引数名を評価し、fun1への呼び出しをcharacterとしてビルドする必要があることです。 enexpr(var_pass)を使用してfun1を呼び出すだけの場合、enexpr(var_pass)fun2で評価されないため、fun2の変数名の概念が失われます。

> bad_fun2 <- function (var_pass) {
    message("Entering bad fun2")
    fun1(rlang::enexpr(var_pass))
}
> bad_fun2(my_var)
#Entering bad fun2
#Entering fun1
rlang::enexpr(var_pass)

その上、fun1fun2も変数名を文字ベクトルとして返さないことに注意してください。返されるオブジェクトはクラスnameです(もちろん、characterに強制変換することもできます)。明るい面は、evalを直接使用できることです。

> ret <- fun2(my_var)
#Entering fun2
#Entering fun1
> as.character(ret)
[1] "my_var"
> class(ret)
[1] "name"
> eval(ret)
[1] 1 2
0
Vongo