美文网首页我爱编程
戏说R语言系列4

戏说R语言系列4

作者: eryesanye | 来源:发表于2018-05-18 22:10 被阅读0次

上一集讲到 R语言是 S语言的一支方言。其实呢, R语言还受另外一款语言的影响,就是Scheme

Scheme是一种函数式编程语言,是Lisp的两种主要方言之一(另一种为 Common Lisp)。不同于 Common Lisp,Scheme遵循极简主义哲学,以一个小型语言核心作为标准,加上各种强力语言工具(语法糖)来扩展语言本身。

上面这段话摘自维基百科。

廖雪峰 在他的 python教程里这样描述函数式编程。

函数式编程......其思想更接近数学计算。
在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。
而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。
对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。

David Springate 在他的博客里讲到了函数式编程的特征,以及函数式编程在 R语言里的应用。

我讲几个印象比较深刻的特征。

向量运算

for循环在各种语言都是很普遍的一种语法。程序员们在写多层复杂嵌套的for循环上都有一些拿手的绝活。

但实际上,R语言是极其不鼓励写for循环的,而是鼓励使用向量计算这种较为抽象的方法。David Springate举了下面这个例子,他分别用for循环和向量计算求1~200000之间的偶数。

for循环计算 向量计算

在这里,我们也计算了这两种方法的运行时间,很明显,用for循环计算并返回结果的时间(31秒多)要远远高于向量计算的时间(0.02秒)。从计算效率上讲,向量计算要优于for循环计算的,这也是为什么 R语言不鼓励使用for循环的原因。

简单一点说,向量计算在处理一个数和一组数字上是没有区别的。例如,求数字2的平方根,在R语言里执行sqrt(2)就可以了。如果求一组数字,例如 1、2、3、4、5,每个数字的平方根,并不需要写成 sqrt(1)、sqrt(2)、sqrt(3)、sqrt(4)、sqrt(5),只要写成 sqrt(1:5) 就可以了。也就是说,sqrt() 这个函数是向量化的,R语言里大部分的函数都是向量化的,所以,这也是R语言可以大量使用向量计算的原因。

C++本来是没有向量运算的,后来出现了Rcpp(为了提升R语言的执行效率,一种可以在R程序里嵌入C++程序,也可以在C++程序里嵌入R程序的工具),考虑到R用户使用向量计算的习惯,特意加了语法糖:可以用向量运算来编写C++程序。实际上,不同语言的相互学习、渗透已经很普遍了。

Lisp甚至没有for循环的语法。R语言虽然是强函数式编程语言,但还是保留了for循环的语法,否则学的人可能就更少了。

高阶函数

高阶函数和向量计算有点类似,如下图所示。高阶函数将输入向量(或矩阵、list、dataframe等数据结构)的每个元素按顺序代入函数中,并将求出的结果按顺序返回。

摘自David Springate的讲义

廖雪峰的python讲义里也提到了python的几个高阶函数,分别是 map/reduce 、filter、sorted,我不知道这是不是python的全部高阶函数。

R语言有一个大类的高阶函数被称为 apply族群,之所以叫“族群”,是因为在最基本的apply()、lapply()、sapply()、Reduce()的基础上,发展了很多工具。例如 Hadley Wickham(前几集一直再讲他)的plyr、dplyr,除此之外,还有更多的类似的工具。作为一种函数式编程语言,只要能想象到的抽象计算,都可以转换成高阶函数。

我个人更喜欢 Hadley Wickham 的 plyr,更有魔力的一种工具。

闭包(closure)

我在javascript看到闭包的概念,R语言也有闭包的概念。

John D Cook 这句 “An object is data with functions. A closure is a function with data.” 说的挺好,对象就是带着函数的数据,闭包就是带着数据的函数。

摘自David Springate的讲义

闭包就是在原有函数的基础上去生产新的函数,或者简称为函数的函数,也就是函数本身可以作为参数代入新的函数里。一些纯函数式编程语言甚至没有变量这个东西,都是函数,想想挺神奇的。

David Springate在讲义里举例说明了闭包的优势。这个案例讲的是如何设计一个 bootstrap 的抽样方案来做一个简单的回归分析。如下图所示。

源代码摘自David Springate讲义

这个是用闭包来编写的,boot_lm是一个函数,iris_boot是在boot_lm基础上的一个新的函数。真正执行的是bstrap那一步。所以说,闭包这种方式的一个好处是,编程者可以在函数定义上不断优化。

同样的问题,David Springate换了一种非函数式编程方法。如下图所示。

源代码摘自David Springate讲义

David Springate 这样评价这段代码 “This ugly beast is full of fors and ifs and braces and brackets and double brackets. It has a load of extra boilerplate code to define the variables and fill the matrices.” ,这个就不翻译了,看起来很愤怒。出于专业精神,我们还是要知道 shit 在哪里。

主要问题其实就是,没有把函数的定义过程和计算过程分离开来,如果执行不下去的话,很难发现到底是哪里出错了。

很多评论说,函数式编程语言是 “ free-debug”的,大概意思就是,只要函数编的好,就不会有太多问题。

网上有一些文章对面向对象编程和函数式编程进行了比较。印象里说 javascript 因为从函数式编程转到面向对象编程,才有了今天的辉煌。也有说,C语言需要一年时间完成开发某个功能,Lisp语言只需要不到三星期。

我觉着实际上没那么夸张。

相关文章

  • 戏说R语言系列4

    上一集讲到 R语言是 S语言的一支方言。其实呢, R语言还受另外一款语言的影响,就是Scheme。 Scheme是...

  • 戏说R语言系列8

    Dirk Eddelbuettel的网站上有很多“EXTENDING R”的内容。 翻译过来是“扩张R”。“扩张”...

  • 戏说R语言系列6

    讲一点R语言的高性能计算。 R语言有自己的官网,https://cran.r-project.org/,页面很“简...

  • 戏说R语言系列 5

    统计之都对 Hadley Wickham的访谈里,提出了一个“社会化编程”的说法,类似Github这样的平台,正在...

  • 戏说R语言系列11

    讲一下有关 R 语言的数据库操作。要想成为一名数据分析师、数据科学家、BI 系统开发人员,或者更加高大上的算法工程...

  • 戏说R语言系列10

    我问过两位以前的同事,如果我想学python,要怎么学?一位说,编程语言相通的地方很多,如果有一些其他语言的基础,...

  • 戏说R语言系列2

    统计之都有一篇对Rstudio公司创始人J.J. Allaire的专访。感兴趣的同学可以抽空看看。 https:/...

  • 戏说R语言系列3

    R是一门很“古老”的语言,可以追溯到20世纪70年代的贝尔实验室。那时候数值计算的主要语言是Fortran,这种语...

  • 戏说R语言系列1

    我一直想写点有关R语言的事儿,可每到落笔的时候,又觉着没什么可写的。 不过写点东西也不算是坏事,权当吃饱了消耗10...

  • 戏说R语言系列9

    讲一下如何用R语言构建区块链。 区块链是年初以来被炒得最火、也最“莫名其妙”火起来的技术。得益于大佬们的集体发声,...

网友评论

    本文标题:戏说R语言系列4

    本文链接:https://www.haomeiwen.com/subject/fcdbdftx.html