属性の付与によるデータ構造の変換
Rが独特なプログラミング言語である理由の1つは、基本的なデータ構造がvectorとlistの2種類しかなく、matrixやdata.frameなど他のクラスのデータ構造がvectorとlistにつけたattributeによって定まるところです。最初から意識する必要はないですが、Rの理解向上にはなるので、ぽちぽち試して見ましょう。
1 ベクターに名前をつける
まずは属性のおさらいです。RはvectorやMatrixの各要素に名前をつけられるのが特徴ですが、属性によって実現されています。
<- 1:3
d attributes(d)
NULL
vecotrをつくっただけでは属性がついていませんが、
names(d) <- c("a", "b", "c")
attributes(d)
$names
[1] "a" "b" "c"
名前をつけると属性に書かれることが分かります。
2 ベクター → 行列
ベクターに属性dim
を付与すると行列になります。
<- 1:9
d attributes(d) <- list(dim=c(3, 3))
class(d) d;
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
[1] "matrix" "array"
簡単ですね。同様にarray
にすることもできます。
属性はリスト構造になっていて、複数の属性を同時に持てます。
逆にdim
を消すとベクターに戻ります。実用上はc(d)
とでもした方が速いのですが、理解のためにやってみましょう。
attributes(d) <- NULL
class(d) d;
[1] 1 2 3 4 5 6 7 8 9
[1] "integer"
Rの世界では構造のあるvectorがmatrixと言えます。
3 リスト → データフレーム
リストの属性を変化させて、データフレームにしてみましょう。 まずはリストを作って、クラスを確認します。
<- list(a=1:3, b=6:8)
d class(d) d;
$a
[1] 1 2 3
$b
[1] 6 7 8
[1] "list"
次に、作ったリストに属性を付与します。
class
とrow.names
を設定すると、
attributes(d) <- list(names=names(d), class="data.frame", row.names=1:max(sapply(d, length)))
class(d) d;
a b
1 1 6
2 2 7
3 3 8
[1] "data.frame"
データフレームに変化したことがわかります。
4 ベクター → ファクター
因子型もベクターに属性を付与した構造になっていますが、名前と値の関係がひっくり返ります。 まずは、文字列のベクターを準備します。
<- c("a", "b", "c")[round(runif(9, min=0.5, max=3.5))]
v v
[1] "c" "c" "a" "c" "b" "a" "a" "b" "c"
aを1,bを2,cを3と文字列ごとに数字を割り当てたベクトルをつくります。
<- unique(sort(v))
n <- 1:length(n)
w names(w) <- n
<- w[v]
v v
c c a c b a a b c
3 3 1 3 2 1 1 2 3
names
属性がついていますが、必要ではないです。
最後に、levels
をc("a", "b", "c")
に、class
をfactorに設定すると因子型になります。
attributes(v) <- list(levels=n, "class"="factor")
class(v) v;
[1] c c a c b a a b c
Levels: a b c
[1] "factor"
4.1 順序付き因子
class
属性にordered
もつけておくと、順序付き因子になります。
attributes(v) <- list(levels=c("c", "a", "b"), "class"=c("ordered", "factor"))
class(v) v;
[1] b b c b a c c a b
Levels: c < a < b
[1] "ordered" "factor"
factorとorderedの順番を誤ってc("factor", "ordered")
とすると、順序付なし因子として扱われるので注意してください1。
levels
の順序を入れ替えたのにお気づきでしょうが、順序付きだとlevels
の順序に応じた比較が可能になります。
sort(v)
[1] c c c a a b b b b
Levels: c < a < b
1] < v[3] v[
[1] FALSE
順序ロジットの被説明変数のためみたいなデータ型ですね。
5 ベクターに属性をつける
パッケージの中だとstructure
で属性をつけているものがぼちぼちあります。
structure(1:6, dim = c(2, 3))
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
dim
属性をつけて、行列にしている例です。
6 まとめ
Rの基本的なデータ構造はvectorとlistしかなく2、matrixとarrayとfactorとdata.frameは属性をつかった拡張に過ぎません。様々なデータのために様々なクラスが用意されていますが、それらもlistです。こう考えると、実に簡素なプログラミング言語であることが分かります。
なお、data.frame
, matrix
, array
,
factor
,
ordered
の方が簡潔に読みやすく書けます。以上のような煩雑な処理は不必要に書くのは避けましょう。