備忘ログ

チラシの裏的備忘録&メモ

Rのmissing()で判定する引数に既定値があっても値を明示的に与えていない場合には引数に値が指定されていないと判断されるというメモ

Rのmissing()という関数についてのメモ。

missing()はRの{base}に含まれている関数で、関数を内部で使用し関数の引数に値が指定されていない場合にTRUEとなるというものとなる。

f <- function(x) missing(x)
f()
## [1] TRUE
f(x = 1)
## [1] FALSE

たとえば次のように引数xが指定されている場合にはその値を返し、そうでない場合には任意の値を返す関数を考えてみると次のように書ける。

f1 <- function(x){
  # xが指定されていない場合は10を返す
  if(missing(x)) 10
  # xが指定されている場合はその値を返す
  else x
}
# 値が指定されていない場合
f1()
## [1] 10
# 値が指定されている場合
f1(1)
## [1] 1

基本的な挙動はこんな感じ。引数が指定されていない場合に「既定値がありません。」というエラー以外に特別なエラーを返したい場合などにも重宝する。

ここからはmissing()をいじっていて気付いたことなのだが、次のように引数xが指定されていない場合に今回はエラーメッセージを出力し処理をストップし、引数が指定された場合にはその値を返す値を出力する関数を考えてみる。この時、値が指定されているかどうかを確認する引数xに既定値として10を指定しておく。

f2 <- function(x = 10){
  if(missing(x)) stop("xが指定されてないとエラーになる")
  else x
}

これは冒頭と同じ様に引数xに値を指定するともちろんその値が返ってくる。

f2(1)
## [1] 1

ここで、x = 10としたいときにf2()xは既定値があるので、引数xの値を明示しないで実行すると次のようになる。

f2()
## Error in f2(): xが指定されてないとエラーになる

xは既定値で10があるんじゃないか?と思うが、明示しないと指定されていない扱いになる模様。

もちろんx = 10と明示するとエラーにならない。

f2(x = 10)
## [1] 10

ここでわかるのは、missing()で判定する引数に既定値があっても、値を明示的に与えていない場合には引数に値が指定されていないと判断されるということ。規定値は値があるがmissing()関数としては指定されていないということのよう。

ドキュメントを読んでみたがこの点についてはぱっとそれがわかるような記載はなかった。

ただこの仕様(仕組み)は{base}の関数でもつかわれており、例えば、{base}solve()関数でLINPACK引数が既定値でFALSEとなっているが、この引数は廃止されているので指定するとエラーがでる。

ソースコード上では

solve.default <- function (a, b, tol = .Machine$double.eps, LINPACK = FALSE, ...) 
{
    if (!missing(LINPACK)) 
        stop("the LINPACK argument has been defunct since R 3.1.0")
        # 以下略
}

となっており、LINPACK規定値のままなにも指定されていなければstop()の処理は行われないが、なにか(規定と同じFALSEであっても)なにか指定するとエラーで終了する処理となっている。

solve(matrix(c(1,2,1,4), 2), matrix(c(10,32), 2))
##      [,1]
## [1,]    4
## [2,]    6
solve(matrix(c(1,2,1,4), 2), matrix(c(10,32), 2), LINPACK = FALSE)
## Error in solve.default(matrix(c(1, 2, 1, 4), 2), matrix(c(10, 32), 2), : the LINPACK argument has been defunct since R 3.1.0

ドキュメントの説明文や、missing()で通常処理するパターンから思ったのとtちょっと違う処理だなと感じた。

この処理を使えば上記のsolve()のように後方互換性のために残しているもう使用しない既定値付きの引数をなにか任意の値で指定した場合に注意喚起メッセージを出したり、処理をストップすることができそうと思った。

こういう仕様が普通なのかよくわからなかったが、そういう仕様だと思えば便利に使えそう。