R-面向对象编程(一)

栏目: R语言 · 发布时间: 6年前

内容简介:S3泛型函数和方法在统一各个模型的使用方式上是最有用的。比如我们可以创建一个线性模型,以不同角度查看模型信息:线性模型本质上是由模型拟合产生的数据字段构成的列表,所以甚至没有明确调用S3泛型函数时,S3方法分派也会自动进行。如果我们输入

内置类和方法

S3泛型函数和方法在统一各个模型的使用方式上是最有用的。比如我们可以创建一个线性模型,以不同角度查看模型信息:

lm1 = lm(mpg ~ cyl + vs, data = mtcars)

线性模型本质上是由模型拟合产生的数据字段构成的列表,所以 lm1 的类型是 list ,但是它的类是 lm ,因此泛型函数根据 lm 选择方法:

typeof(lm1)
#> [1] "list"

class(lm1)
#> [1] "lm"

甚至没有明确调用S3泛型函数时,S3方法分派也会自动进行。如果我们输入 lm1

lm1
#> 
#> Call:
#> lm(formula = mpg ~ cyl + vs, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)          cyl           vs  
#>      39.625       -3.091       -0.939

实际上, print() 函数被默默地调用了:

print(lm1)
#> 
#> Call:
#> lm(formula = mpg ~ cyl + vs, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)          cyl           vs  
#>      39.625       -3.091       -0.939

为什么打印出来的不像列表呢?因为 print() 是一个泛型函数,它为 lm 选择了一个方法来打印线性模型最重要的信息。我们可以调用 getS3method("print", "lm") 获取实际使用的方法与想象的进行验证:

identical(getS3method("print", "lm"), stats:::print.lm)
#> [1] TRUE

print() 展示模型的一个简要版本, summary() 展示更详细的信息。 summary() 也是一个泛型函数,它为模型的所有类提供了许多方法:

summary(lm1)
#> 
#> Call:
#> lm(formula = mpg ~ cyl + vs, data = mtcars)
#> 
#> Residuals:
#>    Min     1Q Median     3Q    Max 
#> -4.923 -1.953 -0.081  1.319  7.577 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)    
#> (Intercept)   39.625      4.225    9.38  2.8e-10 ***
#> cyl           -3.091      0.558   -5.54  5.7e-06 ***
#> vs            -0.939      1.978   -0.47     0.64    
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 3.25 on 29 degrees of freedom
#> Multiple R-squared:  0.728,  Adjusted R-squared:  0.71 
#> F-statistic: 38.9 on 2 and 29 DF,  p-value: 6.23e-09

实际上, summary() 的输出结果也是一个对象,包含的数据都可以被访问。在这个例子里,这个对象是一个列表,是 summary.lm 类,它有可供 print() 选择的自己的方法:

lm1summary = summary(lm1)
typeof(lm1summary)
#> [1] "list"

class(lm1summary)
#> [1] "summary.lm"

查看列表成分:

names(lm1summary)
#>  [1] "call"          "terms"         "residuals"     "coefficients" 
#>  [5] "aliased"       "sigma"         "df"            "r.squared"    
#>  [9] "adj.r.squared" "fstatistic"    "cov.unscaled"

还有一些其他有用的且与模型相关的泛型函数,例如 plot() , predict() 。不同的内置模型和第三方扩展包提供的模型都能实现这些泛型函数。

举例,我们可以对线性模型调用 plot() 函数:

oldpar = par(mfrow = c(2, 2))
plot(lm1)

R-面向对象编程(一)

par(oldpar)

为避免依次生成这4个图,我们用 par() 将绘图区域划分为2x2的子区域。

利用 predict() 我们可以使用模型对新数据进行预测,泛型函数 predict() 自动选择正确的方法用新数据进行预测:

predict(lm1, data.frame(cyl = c(6, 8), vs = c(1, 1)))
#>    1    2 
#> 20.1 14.0

这个函数既可以用在样本内,又可以用在样本外。如果我们为模型提供新数据,它就进行样本外预测。

下面我们创建一幅真实值和拟合值的散点图,看一看线性模型的预测效果:

plot(mtcars$mpg, fitted(lm1))

R-面向对象编程(一)

这里的 fitted() 也是泛型函数,等价于 lm1$fitted.values ,拟合值等于用原始数据得到的预测值,即用原始数据构建的模型预测原始数据, predict(lm1, mtcars)

真实值与拟合值的差称为残差,可以通过另一个泛型函数 residuals() 获得。

plot(density(residuals(lm1)),
     main = "Density of lm1 residuals")

R-面向对象编程(一)

这些泛型函数不仅适用于 lmglm 和其他内置模型,也适用于其他扩展包提供的模型。

例如我们使用 rpart 包,使用前面的数据和公式拟合一个回归树模型。

if(!require("rpart")) install.packages("rpart")
#> 载入需要的程辑包:rpart
library(rpart)
tree_model = rpart(mpg ~ cyl + vs, data = mtcars)

我们之所以能够使用相同的方法, 是因为这个包的作者希望函数调用的方式与调用R内置函数保持一致

typeof(tree_model)
#> [1] "list"
class(tree_model)
#> [1] "rpart"

打印模型:

print(tree_model)
#> n= 32 
#> 
#> node), split, n, deviance, yval
#>       * denotes terminal node
#> 
#> 1) root 32 1130.0 20.1  
#>   2) cyl>=5 21  198.0 16.6  
#>     4) cyl>=7 14   85.2 15.1 *
#>     5) cyl< 7 7   12.7 19.7 *
#>   3) cyl< 5 11  203.0 26.7 *

更详细信息:

summary(tree_model)
#> Call:
#> rpart(formula = mpg ~ cyl + vs, data = mtcars)
#>   n= 32 
#> 
#>       CP nsplit rel error xerror   xstd
#> 1 0.6431      0     1.000  1.089 0.2579
#> 2 0.0893      1     0.357  0.432 0.0811
#> 3 0.0100      2     0.268  0.427 0.0818
#> 
#> Variable importance
#> cyl  vs 
#>  65  35 
#> 
#> Node number 1: 32 observations,    complexity param=0.643
#>   mean=20.1, MSE=35.2 
#>   left son=2 (21 obs) right son=3 (11 obs)
#>   Primary splits:
#>       cyl < 5   to the right, improve=0.643, (0 missing)
#>       vs  < 0.5 to the left,  improve=0.441, (0 missing)
#>   Surrogate splits:
#>       vs < 0.5 to the left,  agree=0.844, adj=0.545, (0 split)
#> 
#> Node number 2: 21 observations,    complexity param=0.0893
#>   mean=16.6, MSE=9.45 
#>   left son=4 (14 obs) right son=5 (7 obs)
#>   Primary splits:
#>       cyl < 7   to the right, improve=0.507, (0 missing)
#>   Surrogate splits:
#>       vs < 0.5 to the left,  agree=0.857, adj=0.571, (0 split)
#> 
#> Node number 3: 11 observations
#>   mean=26.7, MSE=18.5 
#> 
#> Node number 4: 14 observations
#>   mean=15.1, MSE=6.09 
#> 
#> Node number 5: 7 observations
#>   mean=19.7, MSE=1.81

下面对结果进行可视化,得到树图:

oldpar = par(xpd = NA)
plot(tree_model)
text(tree_model, use.n = TRUE)

R-面向对象编程(一)

par(oldpar)

以上所述就是小编给大家介绍的《R-面向对象编程(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

iOS游戏编程之从零开始

iOS游戏编程之从零开始

李华明 / 2013-2 / 59.00元

《iOS游戏编程之从零开始:Cocos2d-x与cocos2d引擎游戏开发》是作者继《android游戏编程之从零开始》热销之后编写的又一本、基于cocos2d—x2.x和cocos2d—iphone版本,讲述ios平台游戏开发的新作。《iOS游戏编程之从零开始:Cocos2d-x与cocos2d引擎游戏开发》分为两个部分共11章,内容主要包括cocos2d—x引擎游戏开发的基础,常用的类、方法及......一起来看看 《iOS游戏编程之从零开始》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具