利用predict()我们可以使用模型对新数据进行预测,泛型函数predict()自动选择正确的方法用新数据进行预测:
这个函数既可以用在样本内,又可以用在样本外。如果我们为模型提供新数据,它就进行样本外预测。
这里的fitted()也是泛型函数,等价于lm1$fitted.values,拟合值等于用原始数据得到的预测值,即用原始数据构建的模型预测原始数据,predict(lm1, mtcars)。
真实值与拟合值的差称为残差,可以通过另一个泛型函数residuals()获得。
这些泛型函数不仅适用于lm、glm和其他内置模型,也适用于其他扩展包提供的模型。
我们之所以能够使用相同的方法,是因为这个包的作者希望函数调用的方式与调用R内置函数保持一致。
在定义泛型函数时,我们创建一个函数去调用UseMethod()出发方法分派。然后对泛型函数想要作用的类创建带有method.class形式的方法函数,同时还要创建带有method.default形式的默认方法来应对所有其他情况。
下面我们创建一个新的泛型函数generic_head(),它有两个参数:输入对象x和需要提取的记录条数n。泛型函数仅仅调用UseMethod(generic_head)来让R根据输入对象x的类执行方法分派。
对原子向量提取前n个元素,因此分别定义generic_head.numeric、generic_head.character等,另外最好定义一个默认方法捕获不能匹配的其他所有情况:
现在我们还没有定义针对data.frame类的方法,所以当我们输入数据框时,函数会自动转向generic_head.default,又因为提取的数量超出列数,所以下面的运行会报错:
列表可能是创建新类时使用最广泛的数据结构,类描述了对象的类型和对象交互作用的方法,其中对象用于存储多种多样、长度不一的数据。
下面我们定义一个叫product的函数,创建一个由name、price和inventory构成的列表,该列表的类是product。我们还将自己定义它的print方法。
上面我们创建了一个列表,然后将它的类替换为product。我们还可以使用structure():
如果我们创建另一个对象,并将两者放入一个列表然后打印,print.product仍然会被调用:
当products以列表形式被打印时,会对每个元素调用print()泛型函数,再由泛型函数执行方法分派。
大多数其他编程语言都对类有正式的定义,而S3没有,所以创建一个S3对象比较简单,但我们需要对输入参数进行充分的检查,以确保创建的对象与所属类内部一致。
除了定义新类,我们还可以定义新的泛型函数。下面创建一个叫value的泛型函数,它通过测量产品的库存值来为product调用实施方法:
上面我们已经演示了创建S3类和泛型函数的过程,有时候我们需要使用原子向量创建新类,下面展示百分比形式向量创建过程。