R のオブジェクトはクラスを持っている。例えば,行列ならば "matrix" である。
> x <- matrix(c(1,0.2,0.3,0.5,0.2,1,0.4,0.6,0.3,0.4,1,0.7,0.5,0.6,0.7,1), 4) > class(x) [1] "matrix"
行列を表示させるために print 関数を呼ぶと,行列が表示される。
> print(x)
[,1] [,2] [,3] [,4]
[1,] 1.0 0.2 0.3 0.5
[2,] 0.2 1.0 0.4 0.6
[3,] 0.3 0.4 1.0 0.7
[4,] 0.5 0.6 0.7 1.0
もし行列の下半分(三角行列)を書きたい場合には新たな関数を作る。書式にこだわらないとすれば以下のような感じ。
print2 <- function(x)
{
n <- nrow(x)
for (i in 1:n) {
cat(x[i, 1:i], "\n")
}
}
print2(x)
このようにしてもよいが,似たような関数がいっぱいできてしまって,「え〜と,下三角行列を書くのは print2 だっけ,print3 だっけ?」ということになる。そこで,x に「下三角行列である」というクラスを与え,単に print(x) とすればちゃんと下三角行列を書いてくれるようにする。
print.trimat <- function(x)
{
n <- nrow(x)
for (i in 1:n) {
cat(x[i, 1:i], "\n")
}
}
x <- matrix(c(1,0.2,0.3,0.5,0.2,1,0.4,0.6,0.3,0.4,1,0.7,0.5,0.6,0.7,1), 4)
class(x) <- "trimat"
print(x)
定義した関数は print.trimat なのに,実際には print 関数を呼んでいる。しかし,print 関数の引数 x のクラスが "trimat" なので,R は print.trimat という関数があるかどうか調べ,実際にあったので print.trimat 関数を使ってくれるのである。面白いのは,単に x と書いただけで,print(x) と同じになるということである。
> x <- matrix(c(1,0.2,0.3,0.5,0.2,1,0.4,0.6,0.3,0.4,1,0.7,0.5,0.6,0.7,1), 4) > class(x) <- "trimat" > print(x) 1 0.2 1 0.3 0.4 1 0.5 0.6 0.7 1 > > > x 1 0.2 1 0.3 0.4 1 0.5 0.6 0.7 1
要するに,何か処理をして結果を特別な書式で書きたいとき,関数の戻り値に "foo" というクラスを与えるようにしておき,別途 print.foo という関数を書いてやればよい。
簡単な例
intsqrt <- function(x)
{
result <- floor(sqrt(x))
class(result) <- "intsqrt"
return(result)
}
print.intsqrt <- function(x)
{
cat("Integer square root is ", x, "\n")
}
print(intsqrt(8))
intsqrt(8)
x <- intsqrt(120)
print(x)
> print(intsqrt(8))
Integer square root is 2
> intsqrt(8)
Integer square root is 2
> x <- intsqrt(120)
> print(x)
Integer square root is 10