情報科学と人工知能のノート

初等的な知識から最新論文の解説まで色々集めていきます.備忘録兼用.

R のデータ構造

とりあえず現状の理解をまとめます。

属性

R オブジェクトには属性というものを割り当てることができます。
そして、全てのオブジェクトは少なくとも mode と length の二つの本質的属性を持っています。
いくつかの属性の値は専用の関数で調べることができます。
また、それ以外の属性の値は attributes 関数で調べることができます。

> a <- 1:4
> mode(a)
[1] "numeric"
> length(a)
[1] 4
> attributes(a)
NULL
> comment(a) <- "a sample"
> attributes(a)
$comment
[1] "a sample"

> b <- matrix(1:4, 2, 2)
> mode(b)
[1] "numeric"
> length(b)
[1] 4
> attributes(b)
$dim
[1] 2 2

> c <- list(1:4)
> mode(c)
[1] "list"
> length(c)
[1] 1
> attributes(c)
NULL

> d <- data.frame(R1=1:4)
> mode(d)
[1] "list"
> length(d)
[1] 1
> attributes(d)
$names
[1] "R1"

$row.names
[1] 1 2 3 4

$class
[1] "data.frame"

> f <- function() return (1)
> mode(f)
[1] "function"
> length(f)
[1] 1
> attributes(f)
$srcref
function() return (1)

ちなみに、属性は「$属性名」で表示されていますが、ドル記号でアクセスできるわけではないようです。

属性の値を変化させたり、属性を追加したりすると、オブジェクトの振る舞いが変わります。

> is(a)
[1] "integer" "numeric" "vector"
[4] "data.frameRowLabels"
> length(a) <- 6
> a
[1] 1 2 3 4 NA NA
> mode(a) <- "complex"
> a
[1] 1+0i 2+0i 3+0i 4+0i NA NA
> is(a)
[1] "complex" "vector"
> attr(a, "dim") <- c(3, 2)
> a
[,1] [,2]
[1,] 1+0i 4+0i
[2,] 2+0i NA
[3,] 3+0i NA
> is(a)
[1] "matrix" "array" "structure" "vector"
> class(a)
[1] "matrix"
> attributes(a)
$dim
[1] 3 2

ちなみに、自分で勝手な属性を与えると、多少挙動が変わりますが本質的に大変なことは特に何もおこりません。

> attr(a, "myattribute") <- c(1, 2, 3)
> a
[,1] [,2]
[1,] 1+0i 4+0i
[2,] 2+0i NA
[3,] 3+0i NA
attr(,"myattribute")
[1] 1 2 3
> attributes(a)
$dim
[1] 3 2

$myattribute
[1] 1 2 3

以上、R オブジェクトの属性についてでした。
内部でどういう処理が行われているのか全く分かりませんが、様々なプリミティブ関数は結局この属性操作をラップしたもの、と見なしてよいのでしょうか?

ベクトルと行列と配列の関係

前の記事でベクトルや行列は配列の特殊化だと書きましたが、意味的にはともかく R の仕様的にはこれが誤りであることが上の記述から分かります。
正しくは、行列や配列はベクトルの特殊化で、dim 属性を持っているベクトルが行列・配列、です。

リストの二重カッコアクセス

[[]] があるのも mode が原因です。

> mode(c[1])
[1] "list"
> mode(c[[1]])
[1] "numeric"