Rのデータフレームは、リストのように異なる型をまとめることができ、行列のように参照や代入ができる、統計解析によく適したデータ構造です。表の型式でデータを保持できます。標準で使えるため、ビルトイン関数などで広く用いられています。
1 リストとの違い
データフレームの便利さを理解するために、リストの不便さを理解しましょう。リストをつくって、i行j列を参照してみるとします。
lst01 <- with(new.env(), {
n <- 100
x <- runif(n)
z <- runif(n)
kn <- round(runif(n, min = 0.5, max = 3.5))
k <- as.factor(letters[kn])
y <- 1 + x - z + (kn==2)*1 + rnorm(n)
r <- list(y, x, z, k)
names(r) <- c("y", "x", "z", "k")
r
})
慣れていれば
[1] 0.3167571
[1] 0.3167571
行列のようにlst01[i, j]
と言う風には参照できません。\(i\)行目のサブセットをつくろうと思うと、lst01[i, ]
と言う風には参照できないので、
y x z k
0.2543368 0.2747747 0.3167571 1.0000000
と書くことになります。代入も同様で、気軽にできません。
データフレームは内部的にはリストの拡張となっているので、リストは簡単にデータフレームに変換できます。変換すると
[1] c
Levels: a b c
y x z k
2 0.78 0.92 0.19 c
という風に、行列と同様に簡潔に操作ができるようになります。
ウィンドウ・アプリケーション開発などではリスト構造のデータが便利だったりするのですが、そのままでは統計解析では煩雑で、データフレームでは便利です。1990年代ではSとそのクローンであるRぐらいでしか見られないものですが、近年ではR以外のプログラミング言語でも統計解析を行うパッケージなどではデータフレームを実装するようになっており、コンセプトの正しさが示されています。
1.1 データフレームの欠点
リストは要素としてリストやデータフレームを入れられますが、データフレームはデータ構造を入れることができません。
2 行列との違い
行列と同様に操作ができるようになっており、nrow
,ncol
,rbind
,cbind
といった関数もそのまま使えます。一方、行列は一次元ベクトルに属性で次元の情報を加えたものなので、一次元ベクトルとして操作することもできますが、データフレームはリストに属性をつけたものなのでそれは出来ません。
3 デーフレームの作成
上の例ではリストをas.dataframe
でデータフレーム化しましたが、ベクトルをつないで作ることもできます。
4 ファイルI/O
データフレームは表なので、CSVファイルやタブ区切りのファイルでの保存が可能です1。逆に、CSVファイルやタブ区切りのファイルを読み込むのに過不足ない機能を提供します。リストは複雑な構造にもなりうるためできません。行列もデータ型が一種類になるためできません。統計データの多くは表形式のテキストファイル型式で提供されることもあり、RのファイルI/Oではデータフレームが多く用いられることになります2。
4.1 テキストファイルに保存
テキストファイルとしてデータフレームを保存する場合は、write.table
を使います。
タブ区切りの場合はsep = "\t"
となります。標準ではrownames
で参照できる行名を出力しようとするので、row.names = FALSE
で抑制しています。
旧いシステムだと標準ではutf-8での出力にならないことには注意しましょう。
4.2 テキストファイルから読み込む
読み込むときは、read.table
を使います。
標準では先頭行が列名として認識しないので、header = TRUE
をつけています。
オプションは多様に取れますが、欠損値はNA
が入ること、#
からはじまる行はコメントとして無視されること、fileEncoding
で文字コード指定ができること3、引数skip
で先頭から何行かを飛ばすことぐらいを知っておくと、?read.table
でヘルプを見なくても済むことが多いと思います。
5 サブセットの作成
行列と同様に行番号や列番号を指定すれば、その番号のサブセットができます。
# yがゼロ以下の行を抽出
df01[df01$y <= 0, ]
# yがゼロより大きく1以下の行を抽出
df01[df01$y > 0 & df01$y <= 1, ]
# y列とk列を抽出
df01[, c("y", "k")]
subset
をつかうと、行の抽出がすっきり書けます。
5.1 頭n行,末尾n行
ベクトルと行列でも使えるのですが、頭n行を抽出するhead
と、末尾n行を抽出するtail
データフレームの状態確認に便利です。
6 ソート
行列でソートすることは稀だと思いますが、データフレームは行列と同様にソートできます。添字で指定した行番号の順序で並び替えたデータフレームが得られるので、order
で順序をつくって指定します。
8 データフレームの結合
IDなどのキー列をつきあわせて、二つのデータフレームを結合させることができます。
標準では二つのデータフレームで同じ名前の列がキーとして使われます。
突き合せにつかうキー列の列名が二つのデータフレームで異なる場合は、それぞれ指定します。
9 データフレームの分割
ベクトルをキーにしたデータフレームの分割はsplit
で簡単にできます。
データフレームの列を使う場合や、多次元に分割する場合はモデル式を使うのが簡単です。
行数を確認すると、合計100行になっています。
[1] "aは30行"
[1] "bは36行"
[1] "cは34行"
モデル式ではなく、ベクトルで指定する事もできます。偶奇でわけてみましょう。