R で print 関数や summary 関数を使って統計モデルの推定結果を表示できる理由
疑問
print
関数は、変数の中身などの表示にも使う汎用的な関数である。
summary
関数も、R にデフォルトで入っている stats パッケージのモデルだけでなく、他の統計モデリングパッケージでもモデル結果の表示にもよく用いられる。
どうやって表示内容を制御しているのだろうか?
例: 線形回帰モデルの推定結果の表示方法
res <- lm(y~x1+x2, data=df)
print(res)
Call:
lm(formula = y ~ x1 + x2, data = df)
Coefficients:
(Intercept) x1 x2
2.0057 0.3052 NA
summary(res)
Call:
lm(formula = y ~ x1 + x2, data = df)
Residuals:
1 2 3 4 5
0.01590 -0.06889 0.01476 -0.01382 0.05205
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.005712 0.065289 30.72 7.58e-05 ***
x1 0.305160 0.002259 135.06 8.95e-07 ***
x2 NA NA NA NA
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.05202 on 3 degrees of freedom
Multiple R-squared: 0.9998, Adjusted R-squared: 0.9998
F-statistic: 1.824e+04 on 1 and 3 DF, p-value: 8.949e-07
S3 システムについて
S3 とは、R のクラスシステムである(AWS のオブジェクトストレージのことではない)。
S3 システムを利用すれば、オブジェクトのクラス属性に応じて関数を変えることが可能である。
例: print 関数
数値ベクトルは、デフォルトでは class は numeric であり、print 関数に入れるとベクトル成分が表示される。
x <- c(1, 2, 3)
class(x)
print(x)
[1] "numeric"
[1] 1 2 3
これを今、無理やり print 関数による表示内容を変えてみる。
そのためには、変数 x
の class を適当な "sample_class"
にしたうえで、print.sample_class
という関数を定義すればよい。
class(x) <- "sample_class"
print.sample_class <- function(x) {
print("Hi! print.sample_class() is called!")
invisible(x)
}
class(x)
print(x)
[1] "sample_class"
[1] "Hi! print.sample_class() is called!"
この時、print.sample_class
は、「print
関数のメソッド」と呼ばれる。
他の言語でよくあるように「sample_class
の print
メソッド」という呼び方はしないらしい。
なお、methods
関数を使うと、メソッドの一覧を表示できる。
試しにprint
関数のメソッドを表示してみると、先ほどの print.sample_class
が含まれていることが確認できる:
methods(print)
[1] print.acf*
[2] print.activeConcordance*
[3] print.anova*
[4] print.aov*
[5] print.aovlist*
(中略)
[164] print.sample_class
(略)
メソッドを持つ関数を自分で作ってみる
先ほどの print
関数のようにデフォルトで用意されている関数以外にも、自分で作った関数にメソッドを持たせることができる。
例えば、以下のように UseMethod
という関数を使って dosomothing
という関数を定義する:
dosomething <- function(object, ...) UseMethod("dosomething")
dosomething
function(object, ...) UseMethod("dosomething")
この時点で先ほどの x
を引数に取っても、エラーになる:
dosomething(x)
Error in UseMethod("dosomething") :
no applicable method for 'dosomething' applied to an object of class "sample_class"
しかし、 先ほどの sample_class
に対応する dosomething
メソッドとして dosomething.sample_class
という関数を定義すると、dosomoething
関数が x
を引数に取れるようになる:
dosomething.sample_class <- function(x) {
print.default("Hi! I'm doing something!")
}
dosomething(x)
[1] "Hi! I'm doing something!"
参考文献
Garrett Grolemund 著(大橋真也 監訳、長尾高弘 訳)「RStudioではじめるRプログラミング入門」(O'REILLY, 2015)
lm 関数の print, summary はどのように定義されているか?
R にデフォルトで入っている stats パッケージの線形回帰関数 lm について、作成したモデルオブジェクトを print
や summary
の引数に取った時の挙動がどのように定義されているかを調べる。
なお、lm 関数のコードはこちらから読むことができる。
作成したモデルのクラス
lm 関数の定義自体はこちらである。
モデル推定結果は z
という変数に入っており、これ最終的な返り値となる。
着目する部分は以下である:
ここで、目的変数 y
が1列のベクトルであれば、変数 z
の class が lm
に指定されている。
print.lm 関数
以下に、print.lm
関数が定義されている:
以前のノートで触れたように、
class が lm
の変数 z
を print
関数の引数にとると、この print.lm
が呼ばれる。
summary 関数と summary.lm 関数
同様に summary
関数に lm
関数で得られた結果を渡した時に何が起きるかを見てみる。
summary
関数は、以下のように定義されている:
したがって、summary.lm
が定義されていれば、lm
関数の返り値を summary
に渡すと、summary.lm
が summary
のメソッドとして認識されて呼ばれる。
そして summary.lm
は以下で定義されている: