Rでは、一重角括弧[]と二重角括弧[[]]でデータの抽出ができます。
一重角括弧[] : vectorの要素、list(data.frameを含む)の一部を取り出したい時に使用
二重角括弧[[]] : list(data.frameを含む)の要素を取り出したい時に使用
両者の使い分け方は上記の通りなのですが、どうにもしっくりこなかったので整理しました。
data.frame(またはlist)から考える
一重括弧[]、二重括弧[[]]について、いろいろ調べた結果、data.frameから考えるとわかりやすく整理できました。
以下のようなdata.frameを考えます。
v列 : 一様乱数
w列 : 標準正規分布に従う乱数
x列 : ランダムに並んだ小文字アルファベット
y列 : 平均50、標準偏差10の正規分布に従う乱数
z列 : ランダムに並んだ1〜12月の英語名
データ数はそれぞれ100個
set.seed(1)
df <- data.frame(v = runif(100),
w = rnorm(100),
x = sample(letters, 100, replace = TRUE),
y = rnorm(100,50,10),
z = sample(month.name, 100, replace = TRUE))
head(df, 5)
v w x y z
1 0.2655087 0.3981059 y 65.19745 June
2 0.3721239 -0.6120264 i 46.91259 March
3 0.5728534 0.3411197 i 37.46710 November
4 0.9082078 -1.1293631 o 56.42241 December
5 0.2016819 1.4330237 y 49.55291 October
このdata.frameから1,3,5列を抜き出し、それをaという変数に代入します。aのclassを調べるとdata.frameになります。
a <- df[c(1,3,5)]
head(a, 5)
class(a)
> a <- df[c(1,3,5)]
> head(a, 5)
v x z
1 0.2655087 y June
2 0.3721239 i March
3 0.5728534 i November
4 0.9082078 o December
5 0.2016819 y October
> class(a)
[1] "data.frame"
aには、double型のデータとcharacter型のデータが含まれ、全データが同じ型にはなっていないので、aがvectorやmatrixでないのは当然で、必然的にaはlistになります(この場合はdata.frameですが、data.frameは本質的にはlistです)。
このことを踏まえると、listやdata.frameに対し一重角括弧[]で任意の列を抽出できるという機能を持つためには、一重角括弧[]の戻り値はlistもしくはdata.frameでなければならないことだと思います。
したがって、data.frameの各列個別の要素にアクセスしたい場合は別の方法で行わなければならず、それが二重角括弧[[]]というわけです。
b <- df[[1]]
head(b, 5)
class(b)
> head(b, 5)
[1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819
> class(b)
[1] "numeric"
二重角括弧[[]]でデータを抽出すると、戻り値の型はvector(この場合はnumeric型のvector)になります。
vectorから考える
vectorに対しては、n番目の要素を取り出すのは、一般に一重括弧[]を使ってx[n]のようにアクセスしますが、vectorで二重角括弧を使ったらどうなるでしょうか?
x <- 1:100
x[2]
x[[2]]
> x[2]
[1] 2
> x[[2]]
[1] 2
x[2]もx[[2]]もいずれも同じ値を取得することができます。でも、二重角括弧[[]]で複数の値を指定するとエラーになります。
x[c(1,3,5)]
x[[c(1,3,5)]]
> x[c(1,3,5)]
[1] 1 3 5
> x[[c(1,3,5)]]
x[[c(1, 3, 5)]] でエラー:
attempt to select more than one element in vectorIndex
[[]]で指定するのが1データの場合は、R内部で何らかの変換が自動的に行われてうまく機能するようですが、複数の要素にアクセスする場合にはエラーになってしまうみたいです。
というわけで、やはりvectorに対しては[]を使うべきということなのかと思います。
その他
Rには、一重括弧[]、二重括弧[[]]の使い方以外でも、わかりにくかったり、間違えやすかったりする箇所があります。こちらのページでそういう点について整理しています。
そもそもRって何ができるの?って思っている方はこちらをどうぞ。
まとめ
一重角括弧[] : ベクトルの要素、リストの一部を取り出したい時に使用
二重角括弧[[]] : リストの要素を取り出したい時に使用
書いていることは、一番始めと変わりませんが、data.frame、listに対して一重角括弧[]を使う場合の戻り値の型を考えると少しはスッキリしてきませんか?