本节书摘来华章计算机出版社《R的极客理想——高级开发篇 A》一书中的第1章,第1.1节,作者:张丹 更多章节内容可以访问云栖社区“异步社区”公众号查看。
问题
如何高效地学习R语言?
引言
最近遇到很多想转行做数据分析的程序员,他们刚开始学习R语言。很多人以为有了其他语言的编程背景,学习R语言就是一件很简单的事情,因而一味地追求速度,但不求甚解。有人说2周就能掌握R语言,但其实掌握的仅仅是R语言的语法,只能算是入门。
R语言的知识体系并非语法这么简单,如果都不了解R的全貌,何谈学好R语言呢?本节将介绍R语言的知识体系结构,并告诉读者如何才能高效地学习R语言。
1.1.1 R语言的知识体系结构
R语言是一门统计语言,主要用于数学建模、统计计算、数据处理、可视化等几个方向,R语言天生就不同于其他的编程语言。R语言封装了各种基础学科的计算函数,我们在R语言编程的过程中只需要调用这些计算函数,就可以构建出面向不同领域、不同业务的、复杂的数学模型。掌握R语言的语法,仅仅是学习R语言的第一步,要学好R语言,需要你要具备基础学科能力(初等数学、高等数学、线性代数、离散数学、概率论、统计学) +业务知识(金融、生物、互联网) +IT技术(R语法、R包、数据库、算法)的结合。所以只有把自己的综合知识水平提升,才真正地学好R语言。换句话说,一旦你学成了R语言,你将是不可被替代的。
1.?R语言的知识体系结构概览
R语言的知识体系结构是复杂的,要想学好R语言,就必须把多学科的知识综合运用,所以最大的难点不在于语言本身,而在于使用者的知识基础和综合运用多学科知识的能力。
首先,让我们从宏观上来看R语言的知识体系结构的全貌,如图1-1所示,然后再分别解释每部分的细节。
图1-1 R语言的知识体系结构概览
图1-1中我将R语言知识体系结构分为3个部分:IT技术+业务知识+基础学科。这仅仅是我对R语言的理解,不排除由于个人阅历有限导致观点片面的问题。
IT技术是计算时代必备的技术之一,R语言就是一种我们应该要掌握的技术。
业务知识是市场经验和法则,不管你在什么公司,都会有自己的产品、销售、市场等,你要了解你的公司有什么产品,客户是谁,怎么才能把产品卖给你的客户。
基础学科是我们这十几年在学校学的理论知识,当初学的时候并不知道是为了什么,毕业后如果你还能掌握一些知识并实际运用,那么这将是你最有价值的竞争力。
每个部分的知识单独看都有其局限性,但如果能把知识两两结合起来,就构成了我们现在的各种技术的创新点。
IT技术+业务知识:创造了阿里巴巴的电子商务帝国,还有腾讯全生态链的社交网络。
IT技术+基础学科:创造了Google搜索的神话,还有华尔街金融不败的帝国。
当然,R语言只是一门计算机语言技术,不能独自承担改写历史的重任,但R语言确实给了我们很大的想象空间,让我们能动手去了解这个世界的规律,找到无穷无尽的交叉点,创造出新的帝国。
如果你和我一样,都能站在这个角度来学习和使用R语言,那么我们一定可以成为并肩向前的同路人。
2.?R语言的基础知识
蓝图总是宏大和美好的,但具体落实将是困难重重的。接下来,我将会梳理思路,把所有的知识点对应到可操作的文档上,希望帮助大家掌握R语言的全貌!
R语言的基础知识,包括R语言的语法、R语言核心包的使用、R语言的内核编程、R语言包的开发以及R语言的虚拟机。
(1)R语言的语法
语法是我们了解R语言的第一步,和所有人一样,我也曾在很短的时间内就掌握了R语言的语法规则、数据结构、基本类型和常用函数等,但其实R语言语法上的坑,远比你知道的多得多。
我举个例子,看谁能准确地回答。比如,最基础的符号操作“=”“<-”“<<-”,三者有什么区别?分别在什么时候用?不要说问题太偏了,实际根本用不到。我的代码里处处都在用这3个符号,只是你不知道而已。在学习R语言的时候,不要用已经掌握的C、Java、Python的经验直接去套R语言的语法,掉坑里的就是这些人。要从头开始学,一路上没有捷径。
R语言是函数式语言,语法自由,命名自由,使用简单,这只是对于普通用户来说的。作为一个有理想的极客,怎么能只停留在语法上呢?R语言是完全面向对象的,你了解什么是面向对象吗?R语言的面向对象打破了R语言原有的自由,但又要兼容原有的自由语法,多么纠结的设计啊,你能体会到吗?并不是记住了R语言的语法,就代表掌握了R语言。里面各种坑,只有自己踩了,再自己爬出来,才是真正的成长。
(2)R语言核心包的使用
R语言同其他语言一样,在软件启动时,为我们提供了7个核心包,其中包括众多的基础函数,如数学计算函数、统计计算函数、日期函数、包加载函数、数据处理函数、函数操作函数和图形设备函数等。通过search()函数,可以查看到R启动时默认加载7个核心包。
> search() # 查看当前环境已加载的R包
[1] ".GlobalEnv" "package:stats" "package:graphics"
[4] "package:grDevices" "package:utils" "package:datasets"
[7] "package:methods" "Autoloads" "package:base"
这7个核心包就是我们构建复杂模型的基础。由于这几个核心包比较底层,很多函数都是用C语言封装的,没有R语言的源代码,而且除了官方文档,几乎没有其他更详细的文档介绍,所以这几个核心包就是学习的门槛。
再问个问题,R语言的所有操作都是函数操作,那么“a<-1:10”语句会被解析为对应什么函数?
> a<-1:10;a # 赋值
[1] 1 2 3 4 5 6 7 8 9 10
答案是,“1:10”对应“seq()”,“<-”对应assign()。
> assign('b',seq(1:10));b # 通过函数赋值
[1] 1 2 3 4 5 6 7 8 9 10
这种对应关系的意义在于,因为R语言是解释型语言,我们可以通过传递一个函数A的句柄,让其他的函数B动态调用这个函数A,这就是动态语言中的闭包特性的使用思路。这种思路在JavaScript中已经被广泛使用了,但在R语言中,却只有核心包的一些函数使用这种语法。在R语言中,这种需要有计算机背景知识的地方还有很多,特别是在考虑如何提升R语言的性能时。所以,不要轻易说自己掌握了R语言,要多想想如何才能把其他语言的基础带到R语言的世界里。
(3)R语言的内核编程
R语言的内核编程又是一个比较复杂的计算机学科的问题。R语言的内核编程应该包括哪些内容呢,除了刚才说的R语言的语法和R的核心包,还有面向对象编程、向量化计算、特殊数据类型、环境空间等。本书将会重点介绍这些内容。
面向对象编程是一种理解和抽象现实世界的方法,主要用于解决复杂问题的设计及实现。在Java的世界里,从2003年我开始接触Java的时候,社区就已经在聊面向对象的程序设计了。对于R语言来说,直到2011年发布的2.12版本,才最终有了RC类型的面向对象实现。面向对象的成熟,标志着R语言已经具备了构建复杂大型应用的能力,但如何真正地把面向对象用好,似乎也并不是统计人擅长的。像Hadley Wickham那样有能力写出面向对象代码的人,在R语言的圈子里,实在是太少了。
向量化计算是R语言特有的一种并行计算方式。在R语言中,向量(vector)是R的基本数据类型,当你对一个向量进行操作时,程序会对向量中的每个元素分别计算,计算结果以向量的形式返回。比如,最常见的两个等长的向量相加。
> 1:10+10:1 # 两个向量相加
[1] 11 11 11 11 11 11 11 11 11 11
向量化计算,在R中有很广泛的应用场景,基本可以取代循环计算,高效地完成计算任务。我们定义两个向量,先相加再求和,run1()函数用向量化计算实现,run2()用循环方法实现。
> a<-1:100000
> b<-100000:1
> run1<-function(){ # 向量化计算
+ sum(as.numeric(a+b))
+ }
> run2<-function(){ # 循环计算
+ c2<-0
+ for(i in 1:length(a)){
+ c2<-a[i]+b[i]+c2
+ }
+ c2
+ }
> system.time(run1()) # 统计run1()函数的执行时间
用户 系统 流逝
0 0 0
> system.time(run2()) # 统计run2()函数的执行时间
用户 系统 流逝
0.14 0.00 0.14
通过运行程序,我们可以清楚地看出,向量化计算要比循环快。当算法越复杂数据量越大的时候,计算的时间差距会越明显。R语言的编程中的一条经验法则就是用向量计算代替所有的循环计算。
R语言中除了那些基本的数据类型,还有一些高级的特殊数据类型,这些特殊数据类型并不是不常用,而是你不知道。S3类型、S4类型、RC类型分别对应R语言支持的三种面向对象编程的数据结构。环境(environment)类型是由内核定义的一个数据结构,由一系列有层次关系的框架(frame)组成,每个环境对应一个框架,用来区别不同的运行时空间(scope)。
在进行R包开发时,环境空间是必须知道的一个知识点。每个环境空间都是环境类型的一个实例。每个R包都会被加载到一个环境空间中,形成有层次关系的、可调用的空间结构。
我们定义的函数和变量都会存在于R语言的环境空间中,通过ls()就可以看到当前环境空间中的这些变量,比如,刚才向量化计算定义的变量和函数。
ls() # 查看当前环境空间的变量
[1] "a" "b" "run1" "run2"
除了我们自己定义的变量和函数之外,环境空间中还有很多其他的变量和函数,比如sum()、length()、system.time()等,我们可以直接使用这些函数,但是它们并不在当前环境空间中,所以直接用ls()是查看不到的。当切换到base的环境空间时,就可以找到sum()的函数定义了。
ls(pattern="^sum$",envir=baseenv()) # 查看base环境空间的变量
[1] "sum"
R语言的内核编程,如同其他语言一样,包括很多的知识细节,并不是只有我提到的这几点。但由于缺少文档,同时R核心技术不普及,所以知道的人不多,会用的人就更少。笔者也在每天探索,期待发现更多的秘密。
(4)R语言包的开发
R语言包的开发是R语言编程中比较困难但又不得不面对的问题,不仅要把上文中所提到的各种R语言技术综合运用在一起,还要符合R语言包的开发规范,并用Latex写好文档,最后提交给CRAN发布。技术问题虽然难,花时间还是可以解决的,但想要在CRAN上发布,那就只能用“难于上青天”来形容了。R语言发展了20多年,只有5000多个包在CRAN上发布,审核不是一般严格啊!我写的gridgame游戏包和chinaWeather天气包,改了很多次都没能通过,都快到要放弃的边缘了。
换个角度想,只有审核严格才能保证用户在安装第三方R语言包的时候不会出错。由于CRAN的审核过于严格,Hadley Wickham也受不了了,他又开发了devtools包,不仅提供了简化R语言包的开发的工具函数,还支持Github社区发布。这样就可以脱离CRAN的束缚,以个人的名义发布各种奇思妙想的R语言包,甚至是“不误正业”的R语言包。
(5)R语言的虚拟机
终于该说我不熟悉的话题了,从我3年多的R语言使用经验来说,还碰不到R语言的虚拟机。不过,网上看到很多高手在生产环境都会重新编译R软件,比如用OpenBLAS加速R的矩阵运算,在虚拟机层实现矩阵的并行化计算,也有用GPU实现矩阵并行计算的;还有牛人把R实现的各种算法都用C++重新实现,然后通过Rcpp封装,直接与R语言的虚拟机进行连接调用。
3.?R语言的第三方包
R语言的第三方包,主要包括在CRAN上的5000多个第三方包,以及其他社区中的R语言包,这些包在各种领域中都发挥着重要的作用。在《R的极客理想——工具篇》一书中,我介绍了30多个包的使用,包括基础工具包(fortunes, formatR, rjson, RJSONIO, Cairo, CaTools)、时间序列包(zoo, xts, xtsExtra)、性能监控包(memoise, profr, lineprof)、R跨平台通信包(Rserve, Rsession, rJava)、R服务器包(Rserve, RSclient, FastRWeb, Websocket)、数据库访问包(RMySQL, rmongodb, rredis, RCassandra, RHive), Hadoop操作包(rhdfs, rmr2, rhbase)等。
还有很多常用的包,比如数据处理包(lubridate, plyr, reshape2, stringr, formatR, mcmc)、机器学习包(nnet, rpart, tree, party, lars, boost, e1071, BayesTree, gaf?it, arules)、可视化包(ggplot2, lattice, googleVis)、地图包(ggmap, RgoogleMaps, rworldmap)等。
R语言对于金融也有很好的支持,有时间序列包(zoo, xts, chron, its, timeDate)、金融分析包(quantmod, RQuantLib, portfolio, quantstrat, blotter, PerformanceAnalytics, TTR, sde, YieldCurve)、风险管理包(parma, evd, evdbayes, evir, extRemes, ismev)等。同时,笔者正在量化投资的创业中,R语言作为系统架构中的算法引擎是在最核心的位置,R语言正用在最有价值的业务中,在后续的《R的极客理想——量化投资篇》一书中,我将会完整地介绍R语言在量化投资系统中的运用。
4.?数学的基础知识
数学的基础知识主要包括初等数学、高等数学、线性代数、概率论、统计学等。我们在大学中曾经学过的各种数学,那些不知道有什么用,只为考试而学的数学,是能真正决定R语言掌握深度的基础知识。
当R语言普及、变成大众化的编程语言以后,入门会越来越容易,第三方包的调用会越来越简单,最后就是拼基础学科功底了,数学就是对所有人来说最难的基础学科。
初等数学,咱们中国人一直都在强调数学是我们的优势,其实强的部分仅限于初等数学,加法口诀和乘法口诀让我们可以口算100以内的四则运算。
高等数学,可能是大学里挂科最多的一门课,很多老师照本宣科让很多学生完全不知所云。直到遇到R,我才恍悟为什么最小二乘法能进行最优化的计算。重新捡起高数是学R的必经之路。
线性代数,直到读完Google的PageRank论文的N年后,我自己才想明白,原来矩阵可以处理海量数据的计算,实现分步式算法与单机算法的一致性。
概率论,通过R语言进行各种分步的随机实验,并把概率密度函数曲线应用到实际的业务中,才让我们理解概率才是可以衡量客观事件发生的指标。
统计学,通过R语言我们可以很简单地构建各种统计模型,利用Bayes分类器判断垃圾邮件,利用回归模型预测未来的房价。
是R语言能让我切身地感受到,数学的基础知识在我们实际生活中的运用;也是R语言拉近了学术界和工业界的距离。如果能把我们从小到大学到的知识串起来,我想每个人都会具备与众不同的知识结构,将会在各行各业实现伟大的创新。
5.?业务知识
业务知识涉及的面非常广,每个人都可以利用自身所处行业的知识,并结合R语言擅长的领域,发现新的机会。R语言擅长的领域包括统计分析、金融分析、数据挖掘、互联网、生物信息学、生物制药、全球地理科学、数据可视化等。
我在软件和互联网行业待了10年,亲身经历了两个行业的高速发展和变迁。技术一波又一波,每年都有新的主题,一路跟下来的人越来越少,虽然新鲜的血液不断补充着,但这些“血液”的能力和经验却远达不到要求,被市场的浮躁扰动着。近些年,中国的创业公司的成功,少有技术创新,大都是商业模式创新和资本运作的成功。
面对着中国资本市场,掌握好业务方面的知识,就是找到了赚钱的法宝。当业务成熟,在大家都懂得游戏规则后,竞争就会变得异常激烈了,像电商、团购、旅游、酒店、游戏都是如此。新领域新业务,才是值得80后90后年轻人奋斗的方向。如火如荼的O2O、互联网金融、物联网、机器人,也许正是2015年的爆发点。如果你又懂技术又懂业务,学习能力又强,你将是下一个帝国的创造者。
6.?跨学科的综合运用能力
再次强调,只要把多种学科知识综合运用,不仅能够成为R语言的一代高手,更能够实现自我的价值。
当IT技术与业务知识完美结合,你会在新兴的市场找到机会。一旦市场成熟后,业务竞争就会变成资本竞争,机会将不复存在。
当IT技术与基础学科相结合,你可以通过科技创新,建立技术壁垒,保持技术优势直到成为行业老大。
如果IT技术、业务知识、基础学科三者同时具备,那么你将是不可被替代的。只要找到属于你的团队,研发出自己的产品,推广给你的用户,你就已经成功了!
R语言可以从IT的角度帮助你实现成功,同时你的成功也将是R语言的成功!
1.1.2 R语言学习
花了很大的篇幅,终于把我理解的R语言的知识体系解释清楚了。那么接下来,我们应该如何高效地学习R语言呢?有句话要说在前头,学习是艰苦的,没有捷径可言,如果你想成功,那么更要面对苦中之苦。正确的学习方法,可以让我们少走弯路,学习别人的经验,会让我们加速成长。
通过上文中对跨学科知识体系的描述,我想大家都应该明白了,要想学好R语言,最大的难点不在于语言本身,而在于使用者的知识基础和综合运用知识的能力。当然,综合运用是要以良好的基础知识为前提的,先抛开业务知识和基础学科的知识不说,只谈IT技术,应该要掌握哪些知识呢?
1.?IT基础知识
对于R语言本身来说,我们需要掌握R语言的基础知识,包括R的语法、R核心包的使用、R语言的内核编程、R语言包的开发以及与业务相关的第三方R语言包的使用。
如果你在学习R语言之前,已经有了很多的Java、Python等编程语言的经验,那么这将帮助你很快熟悉R语言,你只要再补充一些数据分析和数据挖掘算法的知识,就能马上将R语言用在实际的工作中了。
如果你之前是SAS或Matlab数据科学家,那你只需要熟悉R语言的编程语法和第三方R语言包,就能用R语言来完成SAS和Matlab的所有任务。
如果你是BI程序员,平时工作经常有处理数据和可视化的任务,那么你可以边学习R语言边补充一些统计方面的知识,从无味的ETL过程中发现数据的价值。
如果你是一名在读的统计学专业学生,R语言将帮助你把书本上枯燥的知识程序化,让你在学习过程中发现社会的规律。
如果你一直在用Excel并抱怨其功能远远不够,请试一下R语言,你的想法很快就会变成你财富的源泉。
如果你是一名宽客(Quant),还不懂R语言的话,那么你很快就会被市场淘汰。
如果你是一名Hadoop算法工程师,用Java写一个MR算法通常要好几千行,你可试试用RHadoop,十分之一的代码行就可以完成同样的事情。
还有很多可举例说明的故事。R语言可以与各种技术、各种思路相结合,让R语言和你已掌握的知识进行碰撞,你就会变得和别人不一样。
2.?R语言中文图书
邓一硕(博客http://yishuo.org)曾经写过一篇名为《R语言书籍的学习路线图书》的博文,这篇文章很有参考意义。文章分别介绍了R语言的初级入门、高级入门、绘图与可视化、计量经济学、时间序列分析和金融等内容,涉及30多本R语言图书和小册子,但大部分是英文的。
随着时间的推移,这两年R语言方面又增加了好多本新书,中文图书也慢慢地多了起来。我重新定义的R语言中文图书学习路线图,如图1-2所示。
图1-2 R语言中文图书学习路线图
对于不同层次的R语言用户,也有了市场细分。入门的朋友可以从《R语言编程艺术》开始学习;有一定R语言基础的朋友可以阅读《R语言实战》;需要扩展知识面的朋友可以阅读《R的极客理想——工具篇》;在掌握了R语言的各种入门技术后,高级的R语言开发者可以阅读本;用R做可视化的朋友,可以阅读《ggplot2:数据分析与图形艺术》;正在学习统计学的朋友,可以阅读《统计建模与R软件》;准备用R做金融的朋友,可以阅读《时间序列分析及应用:R语言(原书第2版)》和《金融数据分析导论:基于R语言》。
以上推荐的图书,我都亲自读过,予以品质保证。此图书列表将在我的博客中不定期更新,把我读到的好书分享给大家!
3.?R语言中文社区
除了图书,中文的R语言社区和个人博客也在蓬勃发展。统计之都是中国大陆最权威的R语言组织,其中不仅积累了大量高质量的R语言文章,并主办了七届中国R语言会议。统计之都团队成员,还参与翻译了《R语言编程艺术》《R语言实战》《ggplot2:数据分析与图形艺术》《R语言核心技术手册(第2版)》《R数据可视化手册》《R语言统计入门(第2版)》等多本图书。
炼数成金论坛,以数据分析为主题,设有R语言板块,提供在线的R语言入门培训,黄志洪老师的算法讲解超一流。
人大经济论坛,以经管教育为主题,设有R语言板块,以线下培训为主。
4.?R语言中文博客
笔者的个人博客——粉丝日志(http://blog.fens.me),原创了大量的R语言技术实战文章,包括R的极客理想系列文章、RHadoop实践系列文章、R利剑NoSQL系列文章,并写作“R的极客理想”系列图书。
谢益辉的个人博客(http://yihui.name),博客中主要包括各种有趣的技术和吐槽文章。谢益辉是统计之都的创始人,现任RStudio公司程序员,
刘思喆的个人博客——贝吉塔行星(http://www.bjt.name),博客中主要包括R语言企业级应用的文章。刘思喆现任京东推荐算法经理。
李舰的个人博客(http://jliblog.com),博客中主要包括R语言建模的文章。李舰现任Mango Solutions中国区数据总监。
邓一硕的个人博客——格物堂(http://yishuo.org),博客中主要包括R语言金融数据分析的文章。
阿稳的个人博客——不周山(http://www.wentrue.net/blog),博客中主要包括R语言并行技术的文章。
最后,祝大家把R语言学好用好,在各自的领域中找到创新的突破口,实现自我价值,然后反馈给R语言社区,加速R语言的发展壮大。