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