Rで回帰モデルのオブジェクトからモデル式を再構築する

`str`関数を使うとオブジェクトの中身が見えるので、そこから情報を取り出していろいろ利用することができます。
※ちなみに`str`ってStructureの略です。Stringの略ではないんですね～

```sample.R
model <- lm(Sepal.Length ~ . -Species, iris)
model
str(model)

attr(model$terms, "factors")
row <- rownames(attr(model$terms, "factors"))
col <- colnames(attr(model$terms, "factors"))

coefs <- model$coefficients
coefs[names(coefs) != "(Intercept)"]

formula(paste("Sepal.Length ~ ", paste(col, collapse="+")))
as.formula(model)
```

実行結果は以下のとおり

```
> model <- lm(Sepal.Length ~ . -Species, iris)
> model

Call:
lm(formula = Sepal.Length ~ . - Species, data = iris)

Coefficients:
 (Intercept)   Sepal.Width  Petal.Length   Petal.Width  
      1.8560        0.6508        0.7091       -0.5565  
```

モデルはSepal.Lengthを目的変数に、Speciesの項を除いた他すべてを説明変数にしています。
モデル式の中でピリオド（ドット）を指定すると「他すべて」を指定できるのは便利ですね～

```
> str(model)
List of 13
 $ coefficients : Named num [1:4] 1.856 0.651 0.709 -0.556
  ..- attr(*, "names")= chr [1:4] "(Intercept)" "Sepal.Width" "Petal.Length" "Petal.Width"
 $ residuals    : Named num [1:150] 0.0846 0.21 -0.0493 -0.226 -0.0805 ...
  ..- attr(*, "names")= chr [1:150] "1" "2" "3" "4" ...
 $ effects      : Named num [1:150] -71.5659 -1.1884 9.1884 -1.3724 -0.0599 ...
  ..- attr(*, "names")= chr [1:150] "(Intercept)" "Sepal.Width" "Petal.Length" "Petal.Width" ...
 $ rank         : int 4
 $ fitted.values: Named num [1:150] 5.02 4.69 4.75 4.83 5.08 ...
  ..- attr(*, "names")= chr [1:150] "1" "2" "3" "4" ...
 $ assign       : int [1:4] 0 1 2 3
 $ qr           :List of 5
  ..$ qr   : num [1:150, 1:4] -12.2474 0.0816 0.0816 0.0816 0.0816 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : chr [1:150] "1" "2" "3" "4" ...
  .. .. ..$ : chr [1:4] "(Intercept)" "Sepal.Width" "Petal.Length" "Petal.Width"
  .. ..- attr(*, "assign")= int [1:4] 0 1 2 3
  .. ..- attr(*, "contrasts")=List of 1
  .. .. ..$ Species: chr "contr.treatment"
  ..$ qraux: num [1:4] 1.08 1.02 1.11 1.02
  ..$ pivot: int [1:4] 1 2 3 4
  ..$ tol  : num 1e-07
  ..$ rank : int 4
  ..- attr(*, "class")= chr "qr"
 $ df.residual  : int 146
 $ contrasts    :List of 1
  ..$ Species: chr "contr.treatment"
 $ xlevels      :List of 1
  ..$ Species: chr [1:3] "setosa" "versicolor" "virginica"
 $ call         : language lm(formula = Sepal.Length ~ . - Species, data = iris)
 $ terms        :Classes 'terms', 'formula' length 3 Sepal.Length ~ (Sepal.Width + Petal.Length + Petal.Width + Species) - Species
  .. ..- attr(*, "variables")= language list(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)
  .. ..- attr(*, "factors")= int [1:5, 1:3] 0 1 0 0 0 0 0 1 0 0 ...
  .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. ..$ : chr [1:5] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" ...
  .. .. .. ..$ : chr [1:3] "Sepal.Width" "Petal.Length" "Petal.Width"
  .. ..- attr(*, "term.labels")= chr [1:3] "Sepal.Width" "Petal.Length" "Petal.Width"
  .. ..- attr(*, "order")= int [1:3] 1 1 1
  .. ..- attr(*, "intercept")= int 1
  .. ..- attr(*, "response")= int 1
  .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
  .. ..- attr(*, "predvars")= language list(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)
  .. ..- attr(*, "dataClasses")= Named chr [1:5] "numeric" "numeric" "numeric" "numeric" ...
  .. .. ..- attr(*, "names")= chr [1:5] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" ...
 $ model        :'data.frame':  150 obs. of  5 variables:
  ..$ Sepal.Length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
  ..$ Sepal.Width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
  ..$ Petal.Length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
  ..$ Petal.Width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
  ..$ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
  ..- attr(*, "terms")=Classes 'terms', 'formula' length 3 Sepal.Length ~ (Sepal.Width + Petal.Length + Petal.Width + Species) - Species
  .. .. ..- attr(*, "variables")= language list(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)
  .. .. ..- attr(*, "factors")= int [1:5, 1:3] 0 1 0 0 0 0 0 1 0 0 ...
  .. .. .. ..- attr(*, "dimnames")=List of 2
  .. .. .. .. ..$ : chr [1:5] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" ...
  .. .. .. .. ..$ : chr [1:3] "Sepal.Width" "Petal.Length" "Petal.Width"
  .. .. ..- attr(*, "term.labels")= chr [1:3] "Sepal.Width" "Petal.Length" "Petal.Width"
  .. .. ..- attr(*, "order")= int [1:3] 1 1 1
  .. .. ..- attr(*, "intercept")= int 1
  .. .. ..- attr(*, "response")= int 1
  .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
  .. .. ..- attr(*, "predvars")= language list(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)
  .. .. ..- attr(*, "dataClasses")= Named chr [1:5] "numeric" "numeric" "numeric" "numeric" ...
  .. .. .. ..- attr(*, "names")= chr [1:5] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" ...
 - attr(*, "class")= chr "lm"
> 
```

`str`で見てみると、termsやcoefficientsあたりからモデル式の項の名前を取り出せそうです。

```
> attr(model$terms, "factors")
             Sepal.Width Petal.Length Petal.Width
Sepal.Length           0            0           0
Sepal.Width            1            0           0
Petal.Length           0            1           0
Petal.Width            0            0           1
Species                0            0           0
> row <- rownames(attr(model$terms, "factors"))
> col <- colnames(attr(model$terms, "factors"))
> 
> coefs <- model$coefficients
> coefs[names(coefs) != "(Intercept)"]
 Sepal.Width Petal.Length  Petal.Width 
   0.6508372    0.7091320   -0.5564827 
> 
```

こんな感じで名前をとりだして、上記のcolを使ってモデル式を作ってみると

```
> formula(paste("Sepal.Length ~ ", paste(col, collapse="+")))
Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width
```

このとおり、`formula`関数を使って文字列からモデル式を構築することができました。

```
> as.formula(model)
Sepal.Length ~ (Sepal.Width + Petal.Length + Petal.Width + Species) - 
    Species
> 
```

ちなみに単にモデル式を取り出したい場合、`as.formula`関数を使うこともできます。
こっちでは削除した項の情報も入ってるんですね～