R言語には、可変個の引数を取ることができる関数を定義するための便利な機能があります。たとえば、関数_data.frame
_は任意の数の引数を取り、各引数は結果のデータテーブルの列のデータになります。使用例:
_> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
_
関数のシグネチャには、次のような省略記号が含まれます。
_function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
_
同様のことを行い、複数の値を取得し、それらを単一の戻り値に統合する(および他の処理を行う)関数を作成したいと思います。これを行うには、関数内の関数の引数から_...
_を「アンパック」する方法を理解する必要があります。これを行う方法がわかりません。 _data.frame
_の関数定義の関連する行はobject <- as.list(substitute(list(...)))[-1L]
であり、意味がありません。
では、関数の署名から省略記号を、たとえばリストに変換するにはどうすればよいですか?
具体的には、以下のコードで_get_list_from_Ellipsis
_を記述する方法を教えてください。
_my_Ellipsis_function(...) {
input_list <- get_list_from_Ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_Ellipsis_function(a=1:10,b=11:20,c=21:30)
_
これを行うには2つの方法が考えられます。それらはas.list(substitute(list(...)))[-1L]
とlist(...)
です。ただし、これら2つはまったく同じことを行いません。 (違いについては、回答の例を参照してください。)誰もがそれらの間の実際的な違いは何か、私はどちらを使用すべきか教えてもらえますか?
私は答えとコメントを読みましたが、言及されていないことがいくつかあります。
_data.frame
_はlist(...)
バージョンを使用します。コードの断片:
_object <- as.list(substitute(list(...)))[-1L]
mrn <- is.null(row.names)
x <- list(...)
_
object
を使用して列名を処理しますが、x
を使用して最終的な_data.frame
_を作成します。
未評価の_...
_引数を使用するには、_write.csv
_が使用されている_match.call
_コードを参照してください。
Dirkのコメント結果に書いているように、答えはリストのリストではありません。長さ4のリストで、その要素はlanguage
タイプです。最初のオブジェクトはsymbol
-list
、2番目は式_1:10
_などです。それが_[-1L]
_が必要な理由を説明します:それは_...
_の提供された引数から期待されるsymbol
を削除します(常にリストだからです)。
Dirkがsubstitute
が述べるように、「未評価の式を解析ツリー」で返します。
_my_Ellipsis_function(a=1:10,b=11:20,c=21:30)
を呼び出すと、_...
_は引数のリストを「作成」します:list(a=1:10,b=11:20,c=21:30)
およびsubstitute
は、4つの要素のリストにします:
_List of 4
$ : symbol list
$ a: language 1:10
$ b: language 11:20
$ c: language 21:30
_
最初の要素には名前がなく、これはダークアンサーの_[[1]]
_です。私はこの結果を以下を使用して達成します。
_my_Ellipsis_function <- function(...) {
input_list <- as.list(substitute(list(...)))
str(input_list)
NULL
}
my_Ellipsis_function(a=1:10,b=11:20,c=21:30)
_
上記のように、str
を使用して、関数内のオブジェクトを確認できます。
_my_Ellipsis_function <- function(...) {
input_list <- list(...)
output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
return(output_list)
}
my_Ellipsis_function(a=1:10,b=11:20,c=21:30)
int [1:10] 1 2 3 4 5 6 7 8 9 10
int [1:10] 11 12 13 14 15 16 17 18 19 20
int [1:10] 21 22 23 24 25 26 27 28 29 30
$a
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.00 3.25 5.50 5.50 7.75 10.00
$b
Min. 1st Qu. Median Mean 3rd Qu. Max.
11.0 13.2 15.5 15.5 17.8 20.0
$c
Min. 1st Qu. Median Mean 3rd Qu. Max.
21.0 23.2 25.5 25.5 27.8 30.0
_
大丈夫です。 substitute
バージョンを見てみましょう:
_ my_Ellipsis_function <- function(...) {
input_list <- as.list(substitute(list(...)))
output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
return(output_list)
}
my_Ellipsis_function(a=1:10,b=11:20,c=21:30)
symbol list
language 1:10
language 11:20
language 21:30
[[1]]
Length Class Mode
1 name name
$a
Length Class Mode
3 call call
$b
Length Class Mode
3 call call
$c
Length Class Mode
3 call call
_
必要なものではありません。これらの種類のオブジェクトを処理するには、追加のトリックが必要です(_write.csv
_など)。
_...
_を使用する場合は、list(...)
によるシェーンの回答のように使用する必要があります。
list()
を使用して省略記号をリストに変換し、操作を実行できます。
_> test.func <- function(...) { lapply(list(...), class) }
> test.func(a="b", b=1)
$a
[1] "character"
$b
[1] "numeric"
_
したがって、_get_list_from_Ellipsis
_関数はlist
にすぎません。
これの有効な使用例は、操作のために不明な数のオブジェクトを渡したい場合です(c()
またはdata.frame()
の例のように)。ただし、各パラメーターを事前に知っているときに_...
_を使用することはお勧めできません。引数文字列にあいまいさと複雑さを追加するためです(そして、他のユーザーには関数シグネチャが不明瞭になります)。引数リストは、関数ユーザーにとって重要なドキュメントです。
それ以外の場合は、独自の関数引数でパラメーターをすべて公開せずにパラメーターをサブ関数に渡す場合にも役立ちます。これは、機能のドキュメントに記載されています。
シェーンとダークの回答に追加するだけ:比較するのは面白い
get_list_from_Ellipsis1 <- function(...)
{
list(...)
}
get_list_from_Ellipsis1(a = 1:10, b = 2:20) # returns a list of integer vectors
$a
[1] 1 2 3 4 5 6 7 8 9 10
$b
[1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
と
get_list_from_Ellipsis2 <- function(...)
{
as.list(substitute(list(...)))[-1L]
}
get_list_from_Ellipsis2(a = 1:10, b = 2:20) # returns a list of calls
$a
1:10
$b
2:20
現状では、どちらのバージョンも、my_Ellipsis_function
、最初の方が明らかに単純ですが。
あなたはすでに答えの半分を与えました。検討する
R> my_Ellipsis_function <- function(...) {
+ input_list <- as.list(substitute(list(...)))
+ }
R> print(my_Ellipsis_function(a=1:10, b=2:20))
[[1]]
list
$a
1:10
$b
11:20
R>
そのため、これは呼び出しからa
とb
の2つの引数を取り、リストに変換しました。それはあなたが求めたものではなかったのですか?
これは期待どおりに機能します。以下は、対話型セッションです。
> talk <- function(func, msg, ...){
+ func(msg, ...);
+ }
> talk(cat, c("this", "is", "a","message."), sep=":")
this:is:a:message.
>
デフォルト引数を除いて同じ:
> talk <- function(func, msg=c("Hello","World!"), ...){
+ func(msg, ...);
+ }
> talk(cat,sep=":")
Hello:World!
> talk(cat,sep=",", fill=1)
Hello,
World!
>
ご覧のとおり、デフォルトが特定の場合に必要なものではない場合、これを使用して関数内の関数に「余分な」引数を渡すことができます。