[とsapplyには気をつける。

ひとりアドベントカレンダー15日目。
Rはよしなにデータを処理してくれるので、非常に使い勝手が良い。
その一方、よしなに処理しすぎてこちらが泣きをみることがある。
たとえば、Rで使わない人はいないであろう[関数。
data.frameクラスに適用される[.data.frame関数は通常データフレームを返す。

> iris[1:2,1:2]
  Sepal.Length Sepal.Width
1          5.1         3.5
2          4.9         3.0

しかし、返すデータフレームが1列の時はベクトルを返してくる。

> iris[1:2,1]
[1] 5.1 4.9

もう慣れすぎて個人的にはこの挙動に対してなんら疑問を持たないのだが、これは一貫性が無い。
一貫性をもたせる、つまりデータフレームで返すためにはdrop=FALSEとする。

> iris[1:2,1,drop=FALSE]
  Sepal.Length
1          5.1
2          4.9

同様の関数にsapply関数がある。
こちらデフォルトだとベクトルを返すのだが、ベクトルの長さが0の場合はリストを返す。

> sapply(LETTERS[1:3], function(x) x == "B") 
    A     B     C 
FALSE  TRUE FALSE 
> sapply(LETTERS[0], function(x) x == "B")
named list()

これは気を利かせるオプションsimplifyがデフォルトでTRUEとなっているからであり、FALSEにすることで常にリストで返るようになる。

> sapply(LETTERS[1:3], function(x) x == "B", simplify = FALSE)
$A
[1] FALSE

$B
[1] TRUE

$C
[1] FALSE

> sapply(LETTERS[0], function(x) x == "B", simplify = FALSE)
named list()

なお、vapplyはその辺ガチガチに返り値の型と長さも指定できるのでこちらの方が安全ではある。

> vapply(LETTERS[1:3], function(x) x == "B", logical(1))
    A     B     C 
FALSE  TRUE FALSE 
> vapply(LETTERS[0], function(x) x == "B", logical(1))
named logical(0)

この辺りの話はAdvanced Rおよび以下のSOに書いてある。
http://stackoverflow.com/questions/9668456/why-does-sapply-return-a-list
そして翻訳も出る。決断的に1月に出る。

R言語徹底解説

R言語徹底解説