分享

R语言忍者秘笈

 上通下达 2012-12-20
% R语言忍者秘笈
  2
+% 谢益辉,肖楠,坑主三,坑主四……
  3
+
  4
+学一门语言不可能通过两天时间把语法看完了事就行,必须得实战:一来巩固语法,二来增加经验值。本书根据统计之都论坛(<http:///cn/>)六年中近六千帖子和三万回帖整理并加入作者的个人经验而写成。我们找的有这样几种帖子:
  5
+
  6
+1. 版主们被问得怒火丛生,因为同样的问题被问了八百遍了,但论坛规定版主得修炼内力,所以老实版主回帖提供老链接,其它版主默默;
  7
+1. 大家讨论得热火朝天,提出各种解决方案,但某网友一行代码扔出来,让所有人都默默;
  8
+1. 一个帖子当时只有寥寥几个回复,好像没什么人搭理,默默过了两年,楼主突然冒出来说,哇,这一招真管用;
  9
+1. 一个帖子楼主默默写了很久很久,但根本人没有回复,可能当时大家的查克拉都没到那个量级;
  10
+
  11
+总之,我们追求的是高效率的R应用,就像一名忍者,了解大局形势,也善于利用细节,飞檐走壁上天入地,准确而迅速地完成任务。
  12
+
  13
+## 术语说明
  14
+
  15
+foobar
  16
+:   没有特定含义,就是泛指一个对象或名称,有时候也拆开用,比如foo包bar函数,计算机领域常用语,当年这玩意儿可是让我疑惑了好久,究竟啥是foobar哩
  17
+
257 ????? 01-setup.md
... ...
@@ -0,0 +1,257 @@
  1
+# 安装与配置
  2
+
  3
+你有志于成长为一名忍者,很好,那么首先去把火影看完了再来看这本秘笈吧。
  4
+
  5
+当然,不看火影也没关系。咦,怎么有些观众朋友真的离场了?剩下的朋友就别去叫他们了。R这货,是统计学家为统计学开发的一套数据杀器,但那只是对下忍的介绍,对一名上忍来说,必须对它有更全面的认识,否则你查克拉再强、分身再多,在执行任务时也可能会被各种与统计无关的细节给缠死。R的安装有专门的手册,名曰 _R Installation and Administration_ ,我就不说它在哪儿了,你也别问我要,如果你真的那么感兴趣,请自己去找。
  6
+
  7
+哎哎,怎么又有几位客官走了?其实不用这么听话的,忍者得有自己的判断。我不说的原因是R官方的所有手册基本上都很坑爹,R核心团队都是写代码的高手,可是手册写出来都让人昏昏欲睡,一点读的欲望都没有,这样也好,让他们专注于代码开发吧。迄今为止,我唯一看的手册是 _Writing R Extensions_ ,因为我需要写R包,不按它来就没法整;官方手册技术性太强,这也给无数作者创造了写作机会,不然你也不会看到这里来。
  8
+
  9
+## 安装R
  10
+
  11
+R的首页在<http://www.>,你打开之后一定很失望,苍天呐,世上怎么还有这么古董的网站!几乎是纯文本网站(高级码农都这德行),首页上的那幅图已经七八年没换过了,还用着古老的框架技术。算了,不吐槽了,下载链接在左侧,写着CRAN的那地方。你是忍者,所以你当然不能直接去下载就完事,你得了解CRAN(Comprehensive R Archive Network)这一套东西。所谓的C什么AN是自由软件世界常见的软件分发方式,类似的还有为TeX准备的CTAN,为Perl弄的CPAN等。Linux打一出生就是通过网络发布的,直到今天这个特性还是没有变,后面再详谈Linux的问题。Archive Network的大意是这软件有个主服务器,然后在世界各地有一些镜像服务器,上面的文件和主服务器保持同步,这样减轻主服务器的下载压力,并让其它地区的用户能有更快的下载速度(从离自己近的本地服务器下载)。R除了自己的主程序,还有三千多个用户贡献的附加包,以及各种文档,这一大箩筐东西被复制到世界各地几十台服务器上供用户下载。
  12
+
  13
+你是中国用户,可以选一个国内的镜像。这里我们要特别感谢那些志愿提供服务器的单位对自由软件的支持,如厦门大学、中科院、中科大和北京交通大学等。咱们魏太云大版主对这些事情比较关心,国内要是出了新的镜像通常都是他率先报道(例<http:///cn/topic/106549>)。
  14
+
  15
+### R主程序
  16
+
  17
+先说Windows。要是能找到下载地址就去下,找不到的话,可爱的R core给做了一个自动重定向的网页:<http://cran./bin/windows/base/release.htm>,只要点这个链接,你就会下载最新版本的R,地址可以改为相应的本地镜像,如<http://ftp./mirrors/CRAN/bin/windows/base/release.htm>。各位忍者请务必研究这个页面的源代码,搞清楚为什么这个页面会让浏览器自动下载Windows版本的R安装程序。
  18
+
  19
+Windows中安装R注意几点:
  20
+
  21
+1. 把默认安装目录中的R版本号去掉,比如要是R告诉你装在`C:/Program Files/R/R-2.15.0/`,不要接受这个结果,把它改成`C:/Program Files/R/`,原因后面解释;
  22
+1. 避免安装在中文目录下,因为Windows世界的各种鸟语方言编码问题,跟中文有关的东西往往会扯上麻烦;
  23
+1. 用自定义方式安装(装任何软件都用这种方式,你得了解你的软件里有什么组件、装哪儿去了以及有什么选项配置),默认情况下会装上翻译文件,但R的中文翻译实在不咋地,几年前我实在忍不下去了(那View菜单竟然翻译为单字“看”,这上哪儿说理去啊),动手把界面上的词句重新翻译了一下,好歹像人话了,不过R内部还有大量的条目没有翻译或翻译得很差,要是报个错你都不知道它到底在说什么;所以,还不如直接用原生的英文,不要安装翻译文件;
  24
+
  25
+![去掉安装目录中的版本号目录](http://i./bcQGo.png)
  26
+
  27
+![建议不要安装消息翻译文件](http://i./kOphm.png)
  28
+
  29
+关于第1点,2011年4月我跟R core结结实实打了一仗,最终没有人同意我(战场:<http:///GFluEX>)。为什么我认为默认带上版本号是个很糟糕的选择呢?主要是R一直在不断升级中,而在可怜的Windows底下没有直接升级的方式(快投奔Linux吧),必须先卸载老版本,下载新版本再重新安装。默认情况下,新版本装在新目录下,这样就导致你过去的设置或改动可能会出问题,在我的经历中,至少有两点麻烦:
  30
+
  31
+1. PATH环境变量需要手动更新(下一节再说忍者必读的PATH);
  32
+1. 过去安装的附加包要么全部重新安装,要么手工挪动到新目录下;
  33
+
  34
+总之问题就是两个不同版本的R安装在不同目录下,你得废半天劲去更新各种配置。除非你真的需要多个版本,否则建议永远安装在同一个固定目录下。Windows Vista之后的用户还得关心权限问题,这又是Windows坑爹的发明,过去系统目录下(一般是C盘下)可以随便读写,现在要读写必须要弹个对话框让你确认或输密码。R等不了这事儿,所以要是没有写文件的权限,有些事情就得歇菜,例如安装附加包。这种情况下,建议干脆不要装在那个什么`C:/Program Files/`下,而是自己新建一个目录,比如`C:/Software/`,把你自己的软件装在这个目录下,Windows管不着。
  35
+
  36
+再说Linux。前面说了,Linux是嘴里含着互联网出生的,尽管它后面衍生了很多个发行版,多数情况下,软件都可以从发行版的软件仓库中直接安装,不必自行下载,R也不例外,它提供了四种发行版的仓库:Debian、RedHat、OpenSUSE和Ubuntu。我用的Linux发行版是Ubuntu(普通青年的选择),下面简单说说Ubuntu下的安装,这些步骤都在CRAN页面里,看得懂英文就能按照指示做(<http://cran./bin/linux/ubuntu/>)。
  37
+
  38
+首先添加R的软件库,可以从Synaptic软件包管理器中`Settings --> Repositories --> Other Software`然后添加(Add),把那一行`deb`命令贴在文本框中即可,但注意把镜像地址更改为合适的网址。
  39
+
  40
+![在Synaptic中添加R的软件库](http://i./4uZ4M.png)
  41
+
  42
+![添加R软件库的命令行](http://i./0dWk4.png)
  43
+
  44
+由于Linux下的软件库通常需要负责人签名验证安全性,在添加完R的仓库地址之后,还需要把仓库负责人的钥匙信息导入你的系统,这样你的Ubuntu才能放心从那里安装R,导入只是两行命令的事儿(打开终端Terminal敲命令):
  45
+
  46
+```bash
  47
+gpg --keyserver keyserver.ubuntu.com --recv-key E084DAB9
  48
+gpg -a --export E084DAB9 | sudo apt-key add -
  49
+```
  50
+
  51
+这样在Synaptic里刷新一下软件包的信息(Reload),然后搜索`r-base-dev`,钩上,安装即可,或者等价地,用命令行安装:
  52
+
  53
+```bash
  54
+sudo apt-get update
  55
+sudo apt-get install r-base-dev
  56
+```
  57
+
  58
+装完之后基本上就没什么维护的事儿了,因为Ubuntu会定期提醒你软件仓库中什么软件出了新版本,如果你需要更新,只是点一下OK的事情,不像Windows下得手工卸载、下载、安装。唯一可能需要改动的是,如果将来Ubuntu自身的版本升级了,比如从oneiric升级到precise版本,那么上面的软件库地址里的相应版本也需要手工更新。
  59
+
  60
+对传统或高级Linux用户来说,装任何软件都还有一套古老的办法,那就是用伟大的`make`命令从源代码自行编译,很有黑客范儿。大致步骤很简单:从网上下载软件的源代码,通常是一个`*.tar.gz`压缩文件,解压缩,然后在终端中切换目录到解压缩文件夹下,运行:
  61
+
  62
+```bash
  63
+./configure
  64
+make
  65
+sudo make install
  66
+```
  67
+
  68
+这的确是个办法,几乎对任何软件适用。如果你(比如为了用满屏幕的命令行赢取PPMM的盲目崇拜)鼓起勇气尝试这一条路,你可能两个小时装不好。此时你才触碰到Linux的一个核心特征:软件依赖。在Linux世界里,经常存在A软件依赖于B软件,B依赖于C这样的现象,可能是因为开源的缘故,作者经常把自己的软件构建在别人的软件基础之上,这就导致一片依赖的海洋(当然不是所有的软件都有一大串依赖)。R也依赖大量的其它软件包,如果现在那PPMM还在眼巴巴看着你,那么就用这条无敌命令一次性解决依赖问题:
  69
+
  70
+```bash
  71
+sudo apt-get build-dep r-base-dev
  72
+```
  73
+
  74
+这样就一步把所有依赖包都装上了,然后可以按照上面说的`make`的方式编译。否则,就看`./configure`的输出,报告缺啥装啥,看不懂消息就上Google搜,自然会有人告诉你那个缺少的`*.h`头文件对应的是哪个包,就这样熟练的人可能三个小时可以装完,不熟的人大概三天可以装好,这里面尤其是Cairo那套东西,安装起来折磨死人。所以只要不是闲着没事干,不要轻易自行从源文件编译,不管它看起来多酷,当然,把它当作了解Linux的练习是可以的,初级Linux用户看到这一堆东西可能确实有某种自豪感。
  75
+
  76
+那些Linux软件仓库里放的软件实际上也是通过`make`的方式从源文件一步步编译出来的,只不过是服务器上预先编译好了,省去了用户自行编译和解决依赖的麻烦,直接就可以装编好的二进制包。
  77
+
  78
+最后是Mac OS,我没什么经验,不多说,好像就是一个文件下载下来打开就可以用,我不太理解Mac系统管理程序文件的方式。
  79
+
  80
+### R附加包
  81
+
  82
+整个R系统主要是由一系列程序包(Package)组成,第一次装完R可以运行`.packages(TRUE)`查看R自带的包名。除开这些主程序包之外,CRAN上还有数千附加包,由R核心开发团队之外的用户自行提交,这数量级基本上保证用R干啥的都有,所以上天入地飞檐走壁不成问题。
  83
+
  84
+R包数量之大,有两个原因:一是R语言本身的确很强大,而且易开发,我通常非常佩服那些做了很牛的基础工作而且支持插件开发的软件,这需要程序在早期就有很好的设计;二是向CRAN提交包没有门槛,只要服从开源的许可证,什么人都可以写包,无论质量优劣。毫无疑问,CRAN上必然有很差劲的附加包,俗话说,CRAN大了,什么包都有。在安装附加包之前,我们得对包的质量有所判断,所以我们需要某种导航。导航有两种方式,官方的和民间的,后者就是口口相传,前者在CRAN上有一个链接,叫Task Views。
  85
+
  86
+关于这坑爹的程序包导航,没有看过它的用户第一次恐怕还真找不到,因为R主站上没有它的链接。R core的答复让人很伤心无奈,不在主页放链接的原因是怕用户直接访问CRAN主服务器给服务器增加负担,所以这个导航不放主页,而在CRAN镜像上躲猫猫。即,你访问<http://www.>看不到导航,必须去<http://cran.>或其它CRAN镜像才能看到。我当时看到这个解释有点石化的感觉。谁有钱了给R core们捐几台服务器吧!免得以后再看见这么寒碜的回答。
  87
+
  88
+开源软件通常都一定提供源代码包给你,但不一定提供编译好的二进制包,我们知道对计算机来说,它不认识源代码,只能运行编译过的代码。用过C语言的对此应该会有深刻印象,你先写一个`.c`文件,再用编译器把它编译为`.exe`(Windows)或`.so`(Linux)等二进制文件才能运行。R也一样,不仅它自己的主程序有源代码可以下载,附加包也一样有源代码。源代码包的形式通常是一个`*.tar.gz`压缩包,到CRAN主页一看就能找到R自己的源代码,形如`R-x.x.x.tar.gz`,其中`x.x.x`是R的版本号,如`2.14.2`;而关于附加包,可以从CRAN左侧的`Packages`链接进去找到所有附加包的列表页面,然后进入具体的包的页面,如果你已经知道包的名字,则可以用
  89
+
  90
+> http://cran./package=foobar
  91
+
  92
+直接访问`foobar`包的页面。其实忍者根本不来这一套,记那么多没用的步骤干嘛,直接打开Google搜CRAN加包名肯定就找到了。每个包的页面里有包的描述和卸载链接,通常有三个链接,分别对应着源代码(`foobar_x.x.tar.gz`)、Mac二进制包(`foobar_x.x.tgz`)和Windows二进制包(`foobar_x.x.zip`),视你的操作系统你可以选择一个下载。注意二进制包都是编译过的,所以那里面是看不到源代码的;要看源代码,必须下载源代码包解压缩之后才能看到,具体的某个函数定义在哪儿,就靠你的文本编辑器的搜索功能了,或者你的直觉。这一大套什么源代码什么二进制文件对普通青年都没用,只是对想深挖包里函数源代码的忍者提供一个下手的方向。
  93
+
  94
+普通青年在R里面安装附加包只需要用`install.packages()`函数,比如:
  95
+
  96
+```r
  97
+install.packages('animation')
  98
+```
  99
+
  100
+当然我这是强行植入广告,因为**animation**包是我写的。如果你没有指定R的镜像地址,R会首先问你从哪个镜像安装,选一个近的或顺眼的即可。当你第一次运行这个命令时,R会这样思考:
  101
+
  102
+1. 你的R的安装目录可写吗?如果有写的权限,那么就把包装到R安装目录下,比如`C:/Software/R/library/`;
  103
+1. 如果安装不可写,比如你装在Windows关键的系统目录下,或者是Linux的`/usr/`目录下,那么R会问你要不要在你的用户目录下新建一个文件夹用来安装附加包;
  104
+
  105
+现在有一项重要的忍术要学习:用户目录。Windows用户对此可能没有感觉,因为软件都悄磨叽往这个目录下写东西,你也没注意过,比如上网的缓存文件等;Linux下的很多软件都必须使用这个目录,因为其它所有目录对当前用户来说都是没有写权限的(除非以超级用户身份输密码再执行)。用户目录的特征是它往往是当前系统用户可写的目录,而且所有写的数据只对当前用户有效;要是换个用户登录这个系统,前一个用户的数据对现在的用户毫无影响。这就比较适合存放软件的配置资料,每个用户的配置只对个人有效,免得同一个系统的不同用户之间相互干扰。预知用户目录在哪儿,请在R中执行:
  106
+
  107
+```r
  108
+normalizePath('~')
  109
+```
  110
+
  111
+波浪线`~`在操作系统中通常表示用户的根目录,`normalizePath()`函数用来“标准化”一个路径,比如把`~`扩展为真实的物理路径。对于第一次听说用户目录的同学来说,不妨看看自己的用户目录下究竟有多少文件和文件夹:
  112
+
  113
+```r
  114
+# 以.开头的都是隐藏文件
  115
+list.files('~', all.files = TRUE)
  116
+```
  117
+
  118
+前面说道,如果R的安装目录不可写,R会在用户目录下创建一个新目录安装包,默认情况下这个目录名由`R版本号` + 操作系统信息 + `library`构成,但仍然是为了将来升级方面,我不推荐使用R默认的目录名称,因为它带版本号。那么如何人工指定R包的固定安装目录呢?这涉及到更高级的忍术:环境变量。下一节分解。
  119
+
  120
+R包通常都是纯R写成的,但也有掺杂别的程序语言的,比如C/C++/Fortran,这都是需要编译才能用的代码,这种情况下,CRAN服务器一般都会把源程序包预先编译为Windows/Mac二进制包,所以用户通常不需要了解如何编译R程序包(这方面的知识我们留到更后面再详述),直接装就是了,但有一种特别的情况例外,就是R包依赖于外部系统程序,这些程序没有打入R包发布,所以用户需要额外安装单独的外部程序。比如打开**animation**在CRAN上的页面<http://cran./package=animation>可以看到有一栏`SystemRequirements`,它说明了这个包的部分函数依赖于外部程序,如GraphicsMagick。
  121
+
  122
+对Linux用户来说,R默认安装方式就是从源代码包直接编译,此时要是有外部依赖软件,可能就会稍微麻烦一点,比如**XML**包依赖于**libxml2**,装R包**XML**之前,为了这个包能成功编译,必须先装系统软件**libxml2-dev**,注意是dev版本,因为通常这种版本里才含有头文件(`*.h`),Linux下的软件编译通常需要完整源文件。在你头疼之前,应该想到这种问题别人也一定觉得烦,所以必然有另外的办法。CRAN的Debian维护者把一些常用的依赖外部软件的R包集合起来直接放到了Debian的软件仓库中,在服务器端就直接解决依赖并编译好,这样我们就不需要额外安装那些源程序包了。这些特殊的包在Debian/Ubuntu中名为**r-cran-foobar**(全小写),比如我们可以直接安装**XML**包:
  123
+
  124
+```bash
  125
+sudo apt-get install r-cran-xml
  126
+```
  127
+
  128
+类似的头疼R包还有**RGtk2**和**rggobi**等,在Synaptic中一搜就有。安装R包不到万不得已不要去使用蛮力(从源代码编译),不值得耗费那时间,忍者要集中于自己的任务,你最终是要折腾数据去的,不是去写Linux内核的。
  129
+
  130
+R包与包之间就像Linux程序包一样也可能存在依赖关系,通常`install.packages()`会自动处理依赖,如果A包依赖于B包,那么装A的时候会自动装B(这例子没举好,我应该用A和C的),就像Ubuntu下`apt-get install`也能自动解决依赖一样。
  131
+
  132
+## 配置R
  133
+
  134
+软件选项多到底是好事还是坏事?我也不知道,总之R像其它开源软件一样,有无穷的选项可配置。对新手来说,这是地狱;对熟悉的用户来说,这也许是天堂吧。我们主要介绍两个配置文件,`.Renviron`和`.Rprofile`。这两个文件名看起来有点奇怪,怪在哪儿?它们只有扩展名,没有主文件名,平时我们看见的文件名似乎都是`foobar.doc`。在操作系统中有一个默认的规则,凡是以点开头的文件都是隐藏文件,而且通常都是配置文件。前面那句`list.files()`代码你要是运行过,可能就会发现很多以点开头的文件和文件夹。
  135
+
  136
+R启动的时候会在系统的若干位置寻找配置文件,如果文件存在就会使用这些配置。这个巨复杂的启动过程在`?Startup`中有详细说明(问号是R中查看帮助的操作符),这是典型的Linux喜欢干的事情,什么点文件,什么环境变量,用得不亦乐乎。我总觉得这些东西把事情复杂化了,所以我只介绍两个配置文件,要是你愿意折腾那一堆系统环境变量,那么请便,我只介绍`PATH`这一个最重要的系统变量。
  137
+
  138
+### `.Renviron`文件
  139
+
  140
+这个文件是为R自身设置一些环境变量的,这里面的环境变量仅仅对R有效,不改变操作系统的设置。先说一下什么是环境变量:它们是在当前操作系统环境中的一些变量,同一个变量对不同的用户或不同的系统可能取值不同,这些变量对整个系统可见,所以系统内的所有程序都可以读取它们的值,就像我们写程序常常会事先赋值给一些常量供后面的代码使用一样。环境变量不需要有特定的名称,可以任意命名,但有些名称是约定俗成有特定意义的,比如`PATH`。
  141
+
  142
+`.Renviron`文件放在你的用户目录下,也就是`~/`。你可以在R里面直接打开这个文件^[注意Windows下你可能无法用鼠标右键新建文件的方式直接创建这个文件,聪明的Windows只允许用户用命令行创建以点开头的文件名,请问你知道`mkdir`这个命令吗,或者你知道命令行窗口在哪儿打开吗?]:
  143
+
  144
+```r
  145
+# 如果文件不存在,它会被自动创建
  146
+file.edit('~/.Renviron')
  147
+```
  148
+
  149
+我只推荐放一个环境变量在这里,就是`R_LIBS_USER`,它指定R的附加包安装目录,比如这个文件里面可以写:
  150
+
  151
+```bash
  152
+R_LIBS_USER="~/R"
  153
+```
  154
+
  155
+写入这一行设置之后,保存文件,重启R,现在R就知道以后安装R包就优先安装到`~/R`目录下,也就是在用户目录下创建一个名为`R`的文件夹用来存放附加包。因为这个目录是固定的,所以即使将来升级R,R也会使用这个目录装包,你再也不必更新关于包的配置。另外一个好处是,R的附加包和主程序包分开在不同的位置,如果你不想用附加包了,你完全可以一口气把`~/R`删光,而完全不影响R自身的运行;否则,要是R主程序和附加包混在一个目录下(默认情况就是这样,除非主程序目录不可写),对包的管理来说也是大麻烦事。忍者必须把指挥部和小兵分清楚。
  156
+
  157
+### `.Rprofile`文件
  158
+
  159
+前面说到R启动时,会查看一系列文件;其中`.Renviron`文件用来设置一些R要用的环境变量,而`.Rprofile`文件则是一个R代码文件,在R启动时,如果这个文件存在,它会被首先执行。因此,如果我们有一些任务要在R启动时运行,或有一些个人选项要配置,都可以写在这个文件里。Windows下这个文件还可以叫另一个名字,但忍者应该遵守统一的纪律,所以我们只用`.Rprofile`这一个文件名。在R里面同样可以用`file.edit()`函数打开这个文件:
  160
+
  161
+```r
  162
+file.edit('~/.Rprofile')
  163
+```
  164
+
  165
+R的`options()`函数可用来设置R运行时的一些选项,其中一个常用的选项就是CRAN镜像地址,它告诉R应该从哪里安装附加包。这个选项默认为空,所以每次安装包或更新包,R都要跳出来问你选择哪个CRAN镜像,跳多了你可能也觉得烦,所以不如直接事先指定这个选项好了。以下是一种我在`.Rprofile`中的配置:
  166
+
  167
+```r
  168
+options(repos = c(CRAN = "http://streaming.stat./CRAN",
  169
+                  CRANextra = "http://www.stats./pub/RWin"))
  170
+```
  171
+
  172
+因为我在爱荷华州立大学,我们系有CRAN镜像,所以当然从这里安装最快;`CRANextra`主要是为Windows准备的,因为CRAN上有极少数的包没有Windows版本,但牛津大学的Ripley大人好心提供了Windows的二进制编译版本,所以那些包可以从他那边安装。
  173
+
  174
+这个文件中可以放任意R代码,就看各位的想象力和R功力如何了,用好这个文件可以为R编程增加不少方便。因为我是R包开发者,而我常用到**devtools**包,所以我的`.Rprofile`文件中还有一句:
  175
+
  176
+```r
  177
+if (interactive()) {
  178
+  suppressMessages(require(devtools))
  179
+  options(warn = 1)
  180
+}
  181
+```
  182
+
  183
+这段话是什么意思,留给读者思考。
  184
+
  185
+### `PATH`环境变量
  186
+
  187
+写这一节的时候,哥的心情十分复杂,因为这个环境变量之重要、人们对它忽视之极以及某操作系统对它隐藏之深,让哥常常感到深深绝望。普通青年可以跳过本节,但忍者必须对本节了如指掌。以下是在某操作系统上找PATH变量的步骤:
  188
+
  189
+> “我的电脑”(右键)–>“属性”–>“高级”–>“环境变量”–>“系统变量”–>PATH
  190
+
  191
+这里我们可以看到一连串路径。为什么系统要有个PATH变量?原因就是为了能够脱离程序的绝对路径以命令行方式来运行程序,这样使得程序员不必担心你的程序装在什么位置。当你在命令行窗口(Linux系统下叫终端,Terminal)中敲入一个命令时,系统就会从这一系列的PATH路径中去找你敲的这个程序是否存在,如果存在就运行它。Windows系统菜单“开始”–>“运行”(或者快捷键Win + R),输入`cmd`回车运行,就会打开一个命令行窗口。如果你从来没用过这玩意儿,那你肯定是Windows深度中毒者,不妨先玩玩`dir`、`cd ..`等简单的系统命令,你每敲一个命令,系统都会从PATH中找有没有对应的可执行文件,比如敲R就会找R.exe或R.bat之类的程序文件,如果它们都不在PATH下,那么这个命令就会报错。
  192
+
  193
+R有多种调用方式,最常见的就是打开R,在里面输入代码运行,这称为交互式的运行,因为用户可以和R实时交互;我们还可以用非交互式方式运行R,这就需要我们能够在命令行窗口中直接调用R,继而需要R自身的路径在系统PATH变量中。
  194
+
  195
+这个路径在哪儿?如果你记不住自己的R装在哪儿,没关系,打开R,输入`R.home('bin')`就知道了。Windows下通常是类似于`C:/Program Files/R/R-2.xx.x/bin/`这样一个路径。说到这里,我得回音体一句:安装R的时候尽量装在一个不带版本号的目录下,否则将来更新很麻烦,而且每次装新版本的R还得再修改PATH变量,因为bin路径变了。当然,这一切都只对Windows有效(Windows简直就是为了折磨忍者而生的),Linux和Mac用户不用操心这个事情,因为它们的可执行文件通常放在某个特定PATH路径下,比如在Linux下查看R的可执行文件位置,就会发现它在`/usr/bin/`下,而这个目录本身就在PATH里面:
  196
+
  197
+```bash
  198
+$ which R
  199
+/usr/bin/R
  200
+$ echo $PATH
  201
+/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  202
+```
  203
+
  204
+把R的bin路径添加到PATH中之后,可以在命令行窗口中测试一下是否能调用R:
  205
+
  206
+```bash
  207
+R --version
  208
+```
  209
+
  210
+如果上面的命令打印出R的版本号,那么就配置成功了。这里敲R对命令行来说,就是看看PATH中那些路径里有没有一个路径下包含R.exe或者R.bat之类的可执行文件,这就是所谓的“脱离绝对路径运行程序”。由于Linux系统的程序管理方式和Windows不同(可执行文件通常统一放在`/bin/`或者`/usr/bin/`目录下),所以通常没有这些配置痛苦。
  211
+
  212
+为什么要以非交互式的方式运行R?其实这个问题可以扩展为,为什么要用命令行的方式调用程序?这就涉及到图形用户界面(GUI)操作和命令行界面(CLI)的话题了。计算机和人类各有所长,计算机擅长做枯燥的事情,比如玩儿命循环,跑十次和跑十万次对计算机来说只有时间上的差别,但人类肯定受不了多次重复操作;人类应该做的事情就是把自己的意愿写成代码,指示计算机去做。命令行可以做大量的图形界面无法或很难做的事情,比如批量抓取网页解析数据,要是三五个网页,你也许可以复制粘贴到Excel里,可是要是去复制五百个类似的网页,你还愿意去做吗?这样的事情可以用程序批量化处理。当R在PATH中时,操作系统中的任意其它程序都可以直接调用R,而不必知道R究竟安装在什么目录下,这就为所有程序的协作带来了可能(本来这个事情很简单,但被Windows的程序安装方式给复杂化了)。
  213
+
  214
+我们可以写一个R程序文件,比如叫`foobar.R`,里面包含抓取网页的代码,那么我们可以在命令行中直接执行它:
  215
+
  216
+```bash
  217
+R -f foobar.R
  218
+```
  219
+
  220
+R还有另一个可执行文件叫`Rscript`,如果上面的PATH修改成功,我们也可以用`Rscript`命令执行一个R代码文件:
  221
+
  222
+```bash
  223
+Rscript foobar.R
  224
+```
  225
+
  226
+注意这些都是在命令行窗口中运行,而不是打开R,在R里面输入运行。以命令行方式调用R还有一个好处,就是它会新开一个R进程来执行文件,这样保证程序运行环境的干净;相比之下,交互式运行R代码的时候,可能会存在上一段代码中的结果意外“污染”下一段代码的运行,你现在觉得你的程序运行没有问题,但发给别人之后别人无法运行。
  227
+
  228
+关于R作为命令行工具的更多用法,参见:
  229
+
  230
+```bash
  231
+R --help
  232
+```
  233
+
  234
+这是大多数Linux命令常用的查看帮助文件的方式(命令跟着`--help`参数)。
  235
+
  236
+### Windows下的Rconsole文件
  237
+
  238
+前面介绍的是所有系统通用的配置,这里我们再介绍一下Windows独有的一个配置文件:`Rconsole`,它是一个文本文件,它的路径可以直接用R代码找到:
  239
+
  240
+```r
  241
+file.path(R.home('etc'), 'Rconsole')
  242
+```
  243
+
  244
+你可以用任何文本编辑器打开它。这个文件用来配置Windows下R界面的属性,例如界面语言或字体等。Windows下默认的RGui字体是Courier New,如果我们的系统中安装了其它等宽字体,我们可以修改这个配置文件中的`font`项,例如使用DejaVu Sans Mono字体:
  245
+
  246
+```
  247
+font = TT DejaVu Sans Mono
  248
+```
  249
+
  250
+界面语言也是一个常见问题,我们可以修改`language`项为中文(`zh_CN`)或英文(`en`),如:
  251
+
  252
+```
  253
+language = en
  254
+```
  255
+
  256
+修改语言的一个重要原因是R的中文翻译尚欠缺火候,即使是很熟悉R的人,有时也未必能看懂中文错误消息。希望国内有热心志愿者能在这方面做出更多贡献,翻译小组的文件库位于:<https://github.com/r-cn/r-cntrans>。不过忍者必须熟悉英文,仅仅靠翻译的文字很难走远。
  257
+
100 ????? 11-auto-report.md
... ...
@@ -0,0 +1,100 @@
  1
+# 自动化报告
  2
+
  3
+人类和计算机有各自擅长的东西,人擅长下指令,计算机擅长执行指令,而且对计算机来说,一个任务做一遍或是做一百遍可能只有时间上的区别,但一个人要是同一个任务重复做一百遍可能就抓狂了,而且容易出错。先跑个题,我想起来有个[短片](http://v.youku.com/v_show/id_XMjQyNjU3NjA0.html)叫《What is that》(那是什么),讲的是一对父子和一只麻雀的故事,网上一[搜](http://www./gb/jtjy/qzp/56-ai.htm)就可以找到;当然,它的主题并不是关于人不能忍受重复劳动,我只是跑题而已。
  4
+
  5
+另一方面,人还有最大的一个特征就是懒惰;懒没什么错,看怎么个懒法。有人纯粹是混日子的懒,有人是为了更高效率工作而走捷径。用R做自动化报告就是为了提高效率和保证结果可重复。
  6
+
  7
+## 历史
  8
+
  9
+在R的世界里,凡是提到自动化报告,很多人就会想到Sweave,它已经诞生十几年了。它的主要设计思想来自于文学化编程(Literate Programming),这是Knuth大神提出来的一种编程范式,它与传统的结构化编程不同。结构化编程就是写那些循环(for/while)、选择分支(if else)、函数模块之类的代码,让计算机去按设定好的程序结构去执行,而文学化编程则是把代码嵌入所谓的文学作品中,之所以说所谓的,是因为这里的文学不一定真的是那种常规意义下的文学,只是指人类语言而已,相对计算机代码而言。文学化编程的思想很简单:代码和正文混和在同一个文档中,编译的时候既可以把代码抽出来运行得到结果,也可以把正文抽出来形成软件文档。最初它是为了写软件而设计的,这种设计方式的优势显而易见:代码和文档在一起,方便互相更新和照应。比如修改了代码之后可以很快也更新相应的文档段落,而不必像传统方式那样,从源代码文件跳到文档文件中去更新(人的记忆不可靠,这事儿经常忘记,造成代码和文档不一致)。
  10
+
  11
+要使用文学化编程,必须得有一些设定的规则来标记哪些是代码,哪些是正文,否则这事儿没法进行。最早的语法是这样:用`<<>>=`来标记代码的开始,用`@`标记正文的开始,凡是遇到这两类符号,也就意味着要换频道了,下文要标记为代码或正文。例如,
  12
+
  13
+```
  14
+@
  15
+hello, I will do 1 + 2 next:
  16
+
  17
+<<foo>>=
  18
+1 + 2
  19
+@
  20
+
  21
+OK, I'm done now.
  22
+```
  23
+
  24
+这一块文字中包含两段正文和一段代码。编译它的时候,计算机根据前面的规则就知道`<<>>=`下面的是可以运算的代码,而`@`下面是正文,不能当作代码运行。这就是文学化编程的基本思想,它可以很容易移植到自动化报告中来,下面我们再详细说里面的细节问题。Sweave借用了这个思想,把R代码嵌入报告中,编译报告的时候R代码被执行,源文档中的R代码在输出的时候被替换为相应的运行结果,这些结果和原来的报告正文混合起来就形成了一篇有结果的报告。这样,我们只需要维护包含源代码的源文档,让结果文档自动生成,而不要手工运行代码并复制粘贴结果到文档里,这样做既累人又容易出错。记住,只有源代码是可以信赖的。注意我并不是说它的结果一定是对的,或者源代码一定是对的,代码当然可能是错的,但源代码要是错了我们可以检查出来,而要是人工操作哪里出了岔子就很难查错,比如你本来应该点这个按钮,结果你当时点了另一个,如果没有完整的屏幕录像,恐怕追溯结果的来源时就比较困难了。源代码通常是文本文件,可以放入版本控制如GIT或SVN,记录完整的修改历史。附带说一句,版本控制(Version Control)工具是忍者必备工具,后面会讲,你要是不会这东西的话,别跟别人说你看过这本书。
  25
+
  26
+文学化编程最早和TeX结合在一起,因为文档用TeX写漂亮嘛,但这事儿跟Knuth肯定也脱不了关系,因为这位大神就是TeX系统的作者,这是计算机世界的佳话(老人家当年不满意出版社的排版质量,一举自己写了一套高质量排版系统,并写支票奖励发现缺陷的人,奖金都是16进制的1美元,而且金额随缺陷数目递增,我跑远了,各位要是没听说过这些轶事自己搜吧)。于是,计算机代码用某种语言写,比如C语言,而文档用TeX写;要源代码可以抽代码,要文档可以抽文档,皆大欢喜。
  27
+
  28
+Sweave的诞生也跟TeX绑在一起,这就为它后来的应用埋下了悲剧的种子,因为TeX不是一般人能精通的。我用了八年LaTeX,自认为对它还比较熟,但仅限于使用,要是让我去读那些LaTeX包的源代码,我几乎读不懂,太庞大太复杂了。Sweave的设计里处处是硬编码,所以它很难扩展,一直以来只能被框在TeX世界里,曲高和寡。尽管Knuth大人弄出来这样一个牛轰轰的想法,Sweave基本上也把它实现了,但这东西太难推广了。初学者编译TeX文档难免遇到一堆看不懂的错误,进而气馁,最后疏远它。我用了几年Sweave,在这方面也做了很多工作,想让它变得易用一些,比如开发了LyX模块,让用户可以在LyX里面点按钮就可以直接编译得到PDF文件。即便如此,Sweave的深层问题无法解决,很多简单的问题我等了又等(比如设置图片在TeX文档中的宽度),一直没有等到答案,屡屡想重写它,但忍者的基本素质就是忍,没事儿不要重新发明一个东西。2011年底我终于忍不住了,操起键盘重写了一个新包,叫**knitr**。
  29
+
  30
+## knitr包
  31
+
  32
+你要是没学习过Sweave,最好别去花那时间,可以直接跳入**knitr**世界,它兼容Sweave并提供了无限的扩展性,这本书就是用它基于Markdown写的。先举一个hello world例子吧:
  33
+
  34
+
  35
+
  36
+```r
  37
+1 + 2
  38
+```
  39
+
  40
+
  41
+
  42
+```
  43
+## [1] 3
  44
+```
  45
+
  46
+
  47
+
  48
+```r
  49
+dnorm(0)  # 标准正态分布在0处的密度值
  50
+```
  51
+
  52
+
  53
+
  54
+```
  55
+## [1] 0.3989
  56
+```
  57
+
  58
+
  59
+
  60
+```r
  61
+summary(lm(dist ~ speed, data = cars))  # 一个回归
  62
+```
  63
+
  64
+
  65
+
  66
+```
  67
+## 
  68
+## Call:
  69
+## lm(formula = dist ~ speed, data = cars)
  70
+## 
  71
+## Residuals:
  72
+##    Min     1Q Median     3Q    Max 
  73
+## -29.07  -9.53  -2.27   9.21  43.20 
  74
+## 
  75
+## Coefficients:
  76
+##             Estimate Std. Error t value Pr(>|t|)    
  77
+## (Intercept)  -17.579      6.758   -2.60    0.012 *  
  78
+## speed          3.932      0.416    9.46  1.5e-12 ***
  79
+## ---
  80
+## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
  81
+## 
  82
+## Residual standard error: 15.4 on 48 degrees of freedom
  83
+## Multiple R-squared: 0.651,  Adjusted R-squared: 0.644 
  84
+## F-statistic: 89.6 on 1 and 48 DF,  p-value: 1.49e-12 
  85
+## 
  86
+```
  87
+
  88
+
  89
+
  90
+
  91
+上面你看到的是R的输出,其实它的源文件只有5行,1行标记代码开始,3行R代码,1行标记正文开始。
  92
+
  93
+## 编辑器
  94
+
  95
+### LyX
  96
+
  97
+### RStudio
  98
+
  99
+## 其它包
  100
+

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多