0.3 R 语言编程思想
0.3.1 面向对象
R 是一种基于对象的编程语言,即在定义类的基础上,创建与操作对象;数值向量、函数、图形等都是对象。Python的一切皆为对象也适用于 R。
a
b
f
早期和底层 R 语言中的面向对象编程是通过泛型函数来实现的,以 S3 类、S4 类为代表。新出现的 R6 类更适合用来实现通常所说的面向对象编程(OOP),包含类、属性、方法、继承、多态等概念。
面向对象的内容是 R 语言编程的高级内容,有上述基本了解即可,本书不做具体展开,只在附录放一个用 R6类面向对象编程的简单示例,有兴趣的读者可参阅 [@hadley2019]。
0.3.2 面向函数
笼统来说,R 语言就两个事情:数据,对数据应用操作。这个操作就是函数,包括 R 自带的函数,各种扩展包里的函数,自定义的函数。
所以,使用 R 大部分时间都是在与函数打交道,学会了使用函数,R 语言也就学会了一半,**啊?R 这么简单??确实差不多[脚注2],很多人说 R 简单易学,也是因为此。
脚注2: 前提是不把 R 当一门编程语言,只想简单套用现成的算法模型。
编程中的函数,是用来实现某个功能,其一般形式为:
(
你只要把输入给它,它就能在内部进行相应处理,把你想要的返回值给你。
这些输入和返回值,在函数定义时,都要有固定的类型(模具)限制,叫做形参(形式上的参数);在函数调用时,必须给它对应类型的具体数值,才能真正的去做处理,这叫做实参(实际的参数)。
所以,定义函数就好比创造一个模具,调用函数就好比用模具批量生成产品。
使用函数最大的好处,就是将实现某个功能,封装成模具,从而可以反复使用。这就避免了写大量重复的代码,程序的可读性也大大加强。
下面看一个调用函数的例子。比如想做线性回归,通过网络搜索知道是用自带 `lm()` 函数实现。那么先打开该函数的帮助:
?
执行 `?函数名`,若函数来自扩展包需要事先加载包,则在 Rstudio 右下角窗口打开函数帮助界面,一般至少包括如下内容:
- 函数描述
- 函数语法格式
- 函数参数说明
- 函数返回值
- 函数示例
通过阅读函数描述、参数说明、返回值,再调试示例,就能快速掌握该函数的使用。
函数包含很多参数,常用参数往往只是前几个。比如 `lm()` 的常用参数是:
- formula: 设置线性回归公式形式:因变量 ~ 自变量 + 自变量
- data: 提供数据(框)
使用自带的 `mtcars` 数据集演示,按照函数参数要求的对象类型提供实参:
head
model
所有的 R 函数,即使是陌生的,都可以这样来使用。
0.3.3 向量化编程
高级编程语言都提倡向量化编程[脚注3],说白了就是,对一列/矩阵/多维数组的数同时做同样的操作,既提升程序效率又大大简洁代码。
脚注3: 向量化编程中的向量,泛指向量/矩阵/多维数组。
向量化编程,关键是要用整体考量的思维来思考、来表示运算,这需要用到《线性代数》的知识,其实我觉得《线性代数》最有用的知识就是向量/矩阵化表示运算。
比如考虑
若从整体的角度来考量,引入矩阵和向量:
则前面的
可见,向量化表示大大简化了表达式。这放在编程中,就相当于本来用两层 `for` 循环才能表示的代码,简化为了短短一行代码。
向量化编程其实并不难,关键是要转变思维惯式:很多人学完 C 语言后的后遗症,就是首先想到的总是逐元素的 `for` 循环。摆脱这种想法,调动头脑里的《线性代数》知识,尝试用向量/矩阵表示,长此以往,向量化编程思维就有了。
下面以计算决策树算法中的样本经验熵为例来演示向量化编程。
对于数据集 D,
其中,
实际中经常遇到要把数学式子变成代码,与前文自己写代码所谈到的一样,首先你要看懂式子,拿简单实例逐代码片段调试就能解决。
这里 D 是数据集,比如西瓜分类数据:
df
因变量好瓜表示是否为好瓜,取值为 “是” 和 “否”,则 D 分为两类:
从内到外先要计算
Y
p
继续代入公式计算,记住 R 自带函数天然就接受向量做输入参数:
log2
p
-
看着挺复杂的公式用向量化编程,核心代码只有两行:计算 p 和最后一行。这个实例虽然简单,但基本涉及到所有常用的向量化操作:
- 向量与标量做运算
- 向量与向量做四则运算
- 函数作用到向量
参考文献:
【@hadley2019】Hadley Wickham, Advanced R. Advanced R
————————————
版权声明:原创作品,版权所有,禁止用于一切出版。