lapplyを使うときの豆知識

まあdplyrでmutate_each使えやって話になるかもしれないが、外部パッケージを読み込むのがめんどい、もしくは講義などで初心者に教えるのがめんどいときにlapplyを使わなければいけない、そんな場面、あると思います。
しかし、lapplyの結果はリストで返ってくる。

> smp <- data.frame(v1=letters[1:5], v2=LETTERS[1:5],stringsAsFactors = FALSE)
> smp2 <- lapply(smp, function(x)iconv(x, from="CP932", to="UTF-8"))
> smp2
$v1
[1] "a" "b" "c" "d" "e"

$v2
[1] "A" "B" "C" "D" "E"

ここで添え字を指定しない[]を使うと、リストにならない。

> smp3 <- smp
> smp3[] <- lapply(smp3, function(x)iconv(x, from="CP932", to="UTF-8"))
> smp3
  v1 v2
1  a  A
2  b  B
3  c  C
4  d  D
5  e  E

こんなことになる理由は、[<-のコードを見るとわかる。
[<-の中では途中で付値対象xのクラスを取得し、最後の方で返り値にそのクラスを付与している。
つまり、代入対象のオブジェクトのクラスを保存している。

cl <- oldClass(x)
# 中略
class(x) <- cl

一方、通常の付値の場合は代入する値のクラスが用いられる。
したがって、上記コードのsmp2ではlapplyの結果返ってくる「リスト」がそのままsmp2に付値されたのに対し、smp3ではlapplyの結果であるリストに付値対象のクラスであるdata.frameが付与されたため、smp3はデータフレームとなっている。

と、ここまで書いて思ったけど、以下のようにdata.frame関数で明示的に変換する方がわかりやすいですよね。俺は何をだらだら書いてたんだ。

data.frame(lapply(smp3, function(x)iconv(x, from="CP932", to="UTF-8")), stringsAsFactors=FALSE)

まあ、誰かのコードで添字指定の無い[]が出てきたときの豆知識として知っておくと良いかもしれない。