R数据科学笔记:3
第四章:工作流:脚本
迄今为止,我们一直使用RStudio 控制台来运行代码。这是一个非常好的开始,但如果需要创建更复杂的ggplot2 图形或者dplyr 管道,你很快就会发现控制台非常不方便。为了拓展工作空间,我们应该使用RStudio 脚本编辑器。要想打开脚本编辑器,可以点击File 菜单,选择New File,接着选择R Script;也可以使用组合键Ctrl+Shift+N。现在你可以看到4 个窗格。
如果你很重视一段代码,那么脚本编辑器就是存放这段代码的绝好位置。你可以在控制台中不断调试,一旦代码正常运行并输出预期结果,你就可以将其放在脚本编辑器中。当退出RStudio 时,它会自动保存编辑器中的内容,并在重新打开时自动加载编辑器中的内容。尽管如此,我们还是应该定时保存脚本,并做好备份。
4.1 运行代码
脚本编辑器还非常适合建立复杂的ggplot2 图形或较长的dplyr 操作序列。有效使用脚本编辑器的关键是记住最重要的快捷键之一:Ctrl+Enter。这组快捷键会在控制台中执行当前的R 语句。例如,输入以下代码后,如果光标在█ 处,那么按Ctrl+Enter 会运行生成not_cancedlled 的完整命令,并将光标移到下一个语句(即以not_cancelled %>% 开头的语句)。因此,重复按Ctrl+Enter 就可以轻松运行整个脚本:
除了按照语句顺序运行,还可以一次性运行整个脚本:Ctrl+Shift+S。定期运行整个脚本是非常好的做法,可以让你确认脚本中所有重要的代码都没有问题。
4.2 Rstudio自动诊断
脚本编辑器还会利用红色波浪线和边栏的红叉来高亮显示语法错误:
将鼠标移到红叉上就可以看到错误提示:
RStudio 还能找出潜在的代码问题:
第五章:探索性数据分析
5.1 简介
本章将展示如何使用可视化方法和数据转换来系统化地探索数据,统计学家将这项任务称为探索性数据分析(exploratory data analysis,EDA)。EDA 是一个可迭代的循环过程,具有以下作用。
(1) 对数据提出问题。
(2) 对数据进行可视化、转换和建模,进而找出问题的答案。
(3) 使用上一个步骤的结果来精炼问题,并提出新问题。
EDA 并不是具有严格规则的正式过程,它首先是一种思维状态。在EDA 的初始阶段,应该天马行空地发挥想象力,并考察和试验能够想到的所有方法。有些想法是行得通的,有些想法则会无疾而终。当探索更进一步时,你就可以锁定容易产生成果的几个领域,将最终想法整理成文,并与他人进行沟通。
EDA 是所有数据分析过程中的重要环节,因为总是需要考察一下数据质量,即使你可以不费吹灰之力就找出问题。数据清洗只是EDA 的一项具体应用,此时你提出的问题是,数据是否符合预期。要想进行数据清洗,需要使用所有的EDA 工具:可视化、数据转换和建模。
5.2 问题
EDA 期间的目标是获取对数据的理解。进行EDA 的最简单的方式就是将问题作为指导调查研究的工具。提出问题后,这个问题就使得你将注意力集中在数据集中的特定部分,并帮助你进行有关图形、模型和数据转换的决定。
EDA 本质上是一个创造性过程。和多数创造性过程一样,问题的质量关键在于问题的数量。分析过程的开始阶段很难提出有启发性的问题,因为你并不知道数据集中包含了哪些真知灼见。另一方面,你提出的每个新问题都可以揭示数据中的新内容,并增加发现知识的机会。如果在知识发现的基础上不断使用新问题来补充每个老问题,那么你就可以快速地获取数据中最令人感兴趣的部分,并总结出一组发人深省的问题。
对于应该提出什么样的问题来指导我们的研究,现在还没有确定的规则。但有两类问题总是有助于我们在数据中发现知识。我们可以粗略地将这两类问题表述如下。
(1) 变量本身会发生何种变动?
(2) 不同变量之间会发生何种相关变动?
本章剩余部分会继续讨论这两个问题。我们将解释什么是变动,什么是相关变动,并介绍回答这两个问题的几种方法。为了简化讨论,我们先定义几个术语。
• 变量:一种可测量的数量、质量或属性。
• 值:变量在测量时的状态。变量值在每次测量之间可以发生改变。
• 观测:或称个案,指在相同条件下进行的一组测量(通常,一个观测中的所有测量是在同一时间对同一对象进行的)。一个观测会包含多个值,每个值关联到不同的变量。有时我们会将观测称为数据点。
• 表格数据:一组值的集合,其中每个值都关联一个变量和一个观测。如果每个值都有自己所属的“单元”,每个变量都有自己所属的列,每个观测都有自己所属的行,那么表格数据就是整洁的。
5.3 变动
变动是每次测量时数据值的变化趋势。实际生活中很容易看到变动。如果对任意连续型变量进行两次测量,那么会得到两个不同的结果,即使测量的是一个常数(如光速),情况也是如此。每次测量的结果都包括少量误差,误差在每次测量间是不同的。如果测量多个项目(如不同人的眼睛颜色)或进行多次测量(如电池在不同时刻的电量),分类变量也会发生变化。所有变量都有自己的变动模式,可以揭示出一些有趣的信息。理解这种模式的最好方法就是对变量值的分布进行可视化表示。
5.3.1 对分布进行可视化表示
对变量分布进行可视化的方法取决于变量是分类变量还是连续变量。如果仅在较小的集合内取值,那么这个变量就是分类变量。分类变量在R 中通常保存为因子或字符向量。要想检查分类变量的分布,可以使用条形图:
ggplot(data = diamonds) +geom_bar(mapping = aes(x = cut))
条形的高度表示每个x 值中观测的数量,可以使用dplyr::count() 手动计算出这些值:
> diamonds %>%
+ count(cut)
# A tibble: 5 x 2
cut n
<ord> <int>
1 Fair 1610
2 Good 4906
3 Very Good 12082
4 Premium 13791
如果可以在无限大的有序集合中任意取值,那么这个变量就是连续变量。数值型和日期时间型变量就是连续变量的两个例子。要想检查连续变量的分布,可以使用直方图:
ggplot(data = diamonds) +
geom_histogram(mapping = aes(x = carat), binwidth = 0.5)
可以通过dplyr::count() 和ggplot2::cut_width() 函数的组合来手动计算结果:
> diamonds %>%
+ count(cut_width(carat, 0.5))
# A tibble: 11 x 2
`cut_width(carat, 0.5)` n
<fct> <int>
1 [-0.25,0.25] 785
2 (0.25,0.75] 29498
3 (0.75,1.25] 15977
4 (1.25,1.75] 5313
5 (1.75,2.25] 2002
6 (2.25,2.75] 322
7 (2.75,3.25] 32
8 (3.25,3.75] 5
9 (3.75,4.25] 4
10 (4.25,4.75] 1
直方图对x 轴进行等宽分箱,然后使用条形的高度来表示落入每个分箱的观测的数量。在上图中,最高的条形表示几乎有30 000 个观测的carat 值在0.25 和0.75 之间,这两个值分别是条形的左侧值和右侧值。
使用binwidth 参数来设定直方图中的间隔的宽度,该参数是用x 轴变量的单位来度量的。在使用直方图时,你应该试验一下不同的分箱宽度,因为不同的分箱宽度可以揭示不同的模式。例如,如果只考虑重量小于3 克拉的钻石,并选择一个更小的分箱宽度,那么直方图如下所示:
smaller <- diamonds %>%
filter(carat < 3)
ggplot(data = smaller, mapping = aes(x = carat)) +
geom_histogram(binwidth = 0.1)
如果想要在同一张图上叠加多个直方图,那么我们建议你使用geom_freqploy() 函数来代替geom_histogram() 函数。geom_freqploy() 可以执行和geom_histogram() 同样的计算过程,但前者不使用条形来显示计数,而是使用折线。叠加的折线远比叠加的条形更容易理解:
5.3.2 典型值
条形图和直方图都用比较高的条形表示变量中的常见值,而用比较矮的条形表示变量中不常见的值。没有条形的位置表示数据中没有这样的值。为了将这些信息转换为有用的问题,看看是否具有意料之外的情况。
• 哪些值是最常见的?为什么?
• 哪些值是非常罕见的?为什么?这和你的预期相符吗?
• 你能发现任何异乎寻常的模式吗?如何解释?
作为示例,可以从以下直方图发现几个有趣的问题。
• 为什么重量为整数克拉和常见分数克拉的钻石更多?
• 为什么位于每个峰值稍偏右的钻石比稍偏左的钻石更多?
• 为什么没有重量超过3 克拉的钻石?
ggplot(data = smaller, mapping = aes(x = carat)) +
geom_histogram(binwidth = 0.01)
一般来说,相似值聚集形成的簇表示数据中存在子组。为了理解子组,我们提出以下问题。
• 每个簇中的观测是如何相似的?
• 不同簇之间的观测是如何不相似的?
• 如何解释或描述各个簇?
• 为什么有些簇的外观可能具有误导作用?
以下的直方图显示了美国黄石国家公园中的老忠实喷泉的272 次喷发的时长(单位为分钟)。喷发时间似乎聚集成了两组:短喷发(2 分钟左右)和长喷发(4~5 分钟),这两组间几乎没有其他喷发时间:
ggplot(data = faithful, mapping = aes(x = eruptions)) +
geom_histogram(binwidth = 0.25)
5.3.3 异常值
异常值是与众不同的观测或者是模式之外的数据点。有时异常值是由于数据录入错误而产生的;有时异常值则能开辟出一块重要的新科学领域。如果数据量比较大,有时很难在直方图上发现异常值。例如,查看钻石数据集中y 轴变量的分布,唯一能表示存在异常值的证据是,y 轴的取值范围出奇得宽:
ggplot(diamonds) +
geom_histogram(mapping = aes(x = y), binwidth = 0.5)
正常值分箱中的观测太多了,以致于包括异常值的分箱高度太低,因此我们根本看不见(如果仔细观察x 轴0 刻度附近,没准你能发现点什么)。为了更容易发现异常值,我们可以使用coord_cartesian() 函数将y 轴靠近0 的部分放大:
ggplot(diamonds) +
geom_histogram(mapping = aes(x = y), binwidth = 0.5) +
coord_cartesian(ylim = c(0, 50))
coord_cartesian() 函数中有一个用于放大x 轴的xlim() 参数。ggplot2 中也有功能稍有区别的xlim() 和ylim() 函数:它们会忽略溢出坐标轴范围的那些数据。
这样一来,我们就可以看出有3 个异常值,分别位于0、30 左右和60 左右。我们使用
dplyr 将它们找出来:
> unusual <- diamonds %>%
+ filter(y < 3 | y > 20) %>%
+ arrange(y)
> unusual
# A tibble: 9 x 10
carat cut color clarity depth table price x y
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl>
1 1 Very~ H VS2 63.3 53 5139 0 0
2 1.14 Fair G VS1 57.5 67 6381 0 0
3 1.56 Ideal G VS2 62.2 54 12800 0 0
4 1.2 Prem~ D VVS1 62.1 59 15686 0 0
5 2.25 Prem~ H SI2 62.8 59 18034 0 0
6 0.71 Good F SI2 64.1 60 2130 0 0
7 0.71 Good F SI2 64.1 60 2130 0 0
8 0.51 Ideal E VS1 61.8 55 2075 5.15 31.8
9 2 Prem~ H SI2 58.9 57 12210 8.09 58.9
# ... with 1 more variable: z <dbl>
y 变量测量钻石的三个维度之一,单位为毫米。我们知道钻石的宽度不可能是0 毫米,因此这些值肯定是错误的。我们也完全可以认为32 毫米和59 毫米同样是令人难以置信的,这样的钻石长度超过1 英寸(1 英寸=2.54 厘米),简直就是无价之宝!
5.4缺失值
如果在数据集中发现异常值,但只想继续进行其余的分析工作,那么有2 种选择。
• 将带有可疑值的行全部丢弃
diamonds2 <- diamonds %>%
filter(between(y, 3, 20))
不建议使用这种方式,因为一个无效测量不代表所有测量都是无效的。此外,如果数据质量不高,若对每个变量都采取这种做法,那么你最后可能会发现数据已经所剩无几!
• 相反,我们建议使用缺失值来代替异常值。最简单的做法就是使用mutate() 函数创建一个新变量来代替原来的变量。你可以使用ifelse() 函数将异常值替换为NA:
diamonds2 <- diamonds %>%
mutate(y = ifelse(y < 3 | y > 20, NA, y))
ifelse() 函数有3 个参数。第一个参数test 应该是一个逻辑向量,如果test 为TRUE,函数结果就是第二个参数yes 的值;如果test 为FALSE,函数结果就是第三个参数no 的值。
和R 一样,ggplot2 也遵循不能无视缺失值的原则。因为无法明确地绘制出缺失值,所以ggplot2 在绘图时会忽略缺失值,但会提出警告以通知缺失值被丢弃了:
> ggplot(data = diamonds2, mapping = aes(x = x, y = y)) +
+ geom_point()
Warning message:
Removed 9 rows containing missing values (geom_point).
要想不显示这条警告,可以设置na.rm = TRUE:
ggplot(data = diamonds2, mapping = aes(x = x, y = y)) +
geom_point(na.rm = TRUE)
5.5 相关变动
如果变动描述的是一个变量内部的行为,那么相关变动描述的就是多个变量之间的行为。相关变动是两个或多个变量以相关的方式共同变化所表现出的趋势。查看相关变动的最好方式是将两个或多个变量间的关系以可视化的方式表现出来。如何进行这种可视化表示同样取决于相关变量的类型。
5.5.1 分类变量与连续变量
我们经常需要探索连续变量的分布,这种分布按照一个分类变量的值可以分为几个组,就像前面的频率多边形图一样。geom_freqpoly() 的默认外观不太适合这种比较,因为高度是由计数给出的。这就意味着,如果一组观测的数量明显少于其他组的话,就很难看出形状上的差别。举个例子,我们探索一下钻石价格是如何随着质量而变化的:
ggplot(data = diamonds, mapping = aes(x = price)) +
geom_freqpoly(mapping = aes(color = cut), binwidth = 500)
很难看出分布上的差别,因为总体看来各组数量的差别太大了:
按分类变量的分组显示连续变量分布的另一种方式是使用箱线图。箱线图是对变量值分布的一种简单可视化表示,这种图在统计学家中非常流行。每张箱线图都包括以下内容。
• 一个长方形箱子,下面的边表示分布的第25 个百分位数,上面的边表示分布的第75 个
百分位数,上下两边的距离称为四分位距。箱子的中部有一条横线,表示分布的中位数,
也就是分布的第50 个百分位数。这三条线可以表示分布的分散情况,还可以帮助我们
明确数据是关于中位数对称的,还是偏向某一侧。
• 圆点表示落在箱子上下两边1.5 倍四分位距外的观测,这些离群点就是异常值,因此需
要单独绘出。
• 从箱子上下两边延伸出的直线(或称为须)可以到达分布中最远的非离群点处。
使用geom_boxplot() 函数查看按切割质量分类的价格分布:
ggplot(data = diamonds, mapping = aes(x = cut, y = price)) +
geom_boxplot()
虽然看不出太多关于分布的信息,但箱线图更加紧凑,因此可以更容易地比较多个类别(也更适合使用一张图来表示)。与前面的图形一样,我们可以从箱线图中发现违反直觉的现象:质量更好的钻石的平均价格更低!你将在练习中接受这一挑战,说明为什么会这样。
cut 是一个有序因子:“一般”不如“较好”、“较好”不如“很好”,以此类推。因为很多分类变量并没有这种内在的顺序,所以有时需要对其重新排序来绘制信息更丰富的图形。重新排序的其中一种方法是使用reorder() 函数。
例如,我们看一下mpg 数据集中的class 变量。你可能很想知道公路里程因汽车类别的不同会有怎样的变化:
ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
geom_boxplot()
为了更容易发现趋势,可以基于hwy 值的中位数对class 进行重新排序:
ggplot(data = mpg, mapping = aes(
x = reorder(class,hwy,FUN = median),
y = hwy)) +
geom_boxplot()
如果变量名很长,那么将图形旋转90 度效果会更好一些。你可以通过coord_flip() 函数完成这一操作:
5.5.2 两个分类变量
要想对两个分类变量间的相关变动进行可视化表示,需要计算出每个变量组合中的观测数量。完成这个任务的其中一种方法是使用内置的geom_count() 函数:
ggplot(data = diamonds) +
geom_count(mapping = aes(x = cut, y = color))
图中每个圆点的大小表示每个变量组合中的观测数量。相关变动就表示为特定x 轴变量值与特定y 轴变量值之间的强相关关系。
计算变量组合中的观测数量的另一种方法是使用dplyr:
> diamonds %>%
+ count(color, cut)
# A tibble: 35 x 3
color cut n
<ord> <ord> <int>
1 D Fair 163
2 D Good 662
3 D Very Good 1513
4 D Premium 1603
5 D Ideal 2834
6 E Fair 224
7 E Good 933
8 E Very Good 2400
9 E Premium 2337
10 E Ideal 3903
# ... with 25 more rows
接着使用geom_tile() 函数和填充图形属性进行可视化表示:
diamonds %>%
count(color, cut) %>%
ggplot(mapping = aes(x = color, y = cut)) +
geom_tile(mapping = aes(fill = n))
如果分类变量是无序的,那么可以使用seriation 包对行和列同时进行重新排序,以便更清楚地表示出有趣的模式。对于更大的图形,你可以使用d3heatmap 或heatmaply 包,这两个包都可以生成有交互功能的图形。
5.5.3 两个连续变量
对于两个连续变量间的相关变动的可视化表示,我们已经介绍了一种非常好的方法:使用geom_point() 画出散点图。你可以将相关变动看作点的模式。例如,你可以看到钻石的克拉数和价值之间存在一种指数关系:
ggplot(data = diamonds) +
geom_point(mapping = aes(x = carat, y = price))
随着数据集规模的不断增加,散点图的用处越来越小,因为数据点开始出现过绘制,并堆积在一片黑色区域中(如上面的散点图所示)。我们已经介绍了解决这个问题的一种方法,即使用alpha 图形属性添加透度:
ggplot(data = diamonds) +
geom_point(
mapping = aes(x = carat, y = price),
alpha = 1 / 100
)
但是很难对特别大的数据集使用透明度。另一种解决方法是使用分箱。我们之前使用了geom_histogram() 和geom_freqpoly() 函数在一个维度上进行分箱,现在学习如何使用geom_bin2d() 和geom_hex() 函数在两个维度上进行分箱。
geom_bin2d() 和geom_hex() 函数将坐标平面分为二维分箱,并使用一种填充颜色表示落入每个分箱的数据点。geom_bin2d() 创建长方形分箱。geom_hex() 创建六边形分箱。要想使用geom_hex(),需要安装hexbin 包:
ggplot(data = smaller) +
geom_bin2d(mapping = aes(x = carat, y = price))
ggplot(data = smaller) +
geom_hex(mapping = aes(x = carat, y = price))
另一种方式是对一个连续变量进行分箱,因此这个连续变量的作用就相当于分类变量。接下来就可以使用前面学过的对分类变量和连续变量的组合进行可视化的技术了。例如,你可以对carat 进行分箱,然后为每个组生成一个箱线图:
ggplot(data = smaller, mapping = aes(x = carat, y = price)) +
geom_boxplot(mapping = aes(group = cut_width(carat, 0.1)))
以上示例使用了cut_width(x, width) 函数将x 变量分成宽度为width 的分箱。默认情况下,不管其中有多少个观测,箱线图看上去都差不多(除了离群点的数量不同),因此很难分辨出每个箱线图是对不同数量的观测进行摘要统计的。如果想要体现这种信息,可以使用参数varwidth = TRUE 让箱线图的宽度与观测数量成正比。
另一种方法是近似地显示每个分箱中的数据点的数量,此时可以使用cut_number() 函数:
ggplot(data = smaller, mapping = aes(x = carat, y = price)) +
geom_boxplot(mapping = aes(group = cut_number(carat, 20)))
5.6 模式和模型
数据中的模式提供了关系线索。如果两个变量之间存在系统性的关系,那么这种关系就会
在数据中表现为一种模式。如果发现了模式,需要问自己以下几个问题。
• 这种模式的出现会不会是一种巧合(也就是随机的偶然因素)?
• 应该如何描述这种模式中隐含的关系?
• 这种模式中隐含的关系有多强?
• 其他变量会如何影响这种关系?
• 如果对数据的独立分组进行检查,这种关系会有所变化吗?
我们就前面提到的美国黄石国家公园中老忠实喷泉的喷发时长和两次喷发之间的等待时间
做出一张散点图,该图会显示出一个模式:较长的等待时间与较长的喷发时间是相关的。
图中还显示出两个簇,这个我们之前就发现了:
ggplot(data = faithful) +
geom_point(mapping = aes(x = eruptions, y = waiting))
模式是数据科学中最有效的工具之一,因为其可以揭示相关变动。如果说变动会生成不确定性,那么相关变动就是减少不确定性。如果两个变量是共同变化的,就可以使用一个变量的值来更好地预测另一个变量的值。如果相关变动可以归因于一种因果关系(一种特殊情况),那么就可以使用一个变量的值来控制另一个变量的值。
模型是用于从数据中抽取模式的一种工具。例如,我们思考一下钻石数据。切割质量与价格之间的关系是很难理解的,因为切割质量和克拉数以及克拉数和价格之间是紧密相关的。我们可以使用模型去除价格和克拉数之间的强关系,这样就可以继续研究剩余的微妙关系。以下代码拟合了一个模型,可以根据carat 预测price,并计算出残差(预测值和实际值之间的差别)。一旦去除克拉数对价格的影响,残差就能反映出钻石的价格:
library(modelr)
mod <- lm(log(price) ~ log(carat), data = diamonds)
diamonds2 <- diamonds %>%
add_residuals(mod) %>%
mutate(resid = exp(resid))
ggplot(data = diamonds2) +
geom_point(mapping = aes(x = carat, y = resid))
去除克拉数和价格之间的强关系后,就可以看到预料中的切割质量与价格的关系,对于同样大小的钻石,切割质量更好的钻石更昂贵:
ggplot(data = diamonds2) +
geom_boxplot(mapping = aes(x = cut, y = resid))
5.7 ggplot2调用
通常情况下,一个函数的前一个或前两个参数是非常重要的,你应该将它们牢记于心。ggplot() 函数的前两个参数是data 和mapping,aes() 函数的前两个参数是x 和y。在本书剩余的部分中,我们不再写出这些参数名,这样既可以节省输入时间,也可以让代码样板更精简,以便更容易找出两张图之间的不同之处。
ggplot(data = faithful, mapping = aes(x = eruptions)) +
geom_freqpoly(binwidth = 0.25)
ggplot(faithful, aes(eruptions)) +
geom_freqpoly(binwidth = 0.25)
第六章:工作流:项目
6.1什么是真实的
作为R 的一名新手,你可以认为自己的R 环境(也就是环境窗格中列出的那些对象)是“真实的”。但从长远来看,你最好认为R 脚本是“真实的”。可以通过R 脚本(以及数据文件)重建R 环境,但在R 环境中重建R 脚本就要困难得多!要么被迫重敲一次内存中的代码(伴随着各种输入错误),要么被迫在R 历史记录中埋头翻找。为了培养良好的使用习惯,我们强烈建议你指示RStudio 不在两次会话间保存工作空间。
6.2 你的分析位于哪里
R 中有个名为工作目录的重要概念。R 在这个目录中查找你要加载的文件,也将你要保存的文件放在这个目录中。RStudio 在控制台上方显示当前工作目录。
可以通过运行getwd() 命令在R 代码中输出这个目录:
> getwd()
[1] "C:/Users/zszpc/Documents"
作为R 语言新手,你可以使用自己的主目录、文档目录或计算机上其他稀奇古怪的目录作为R 的工作目录。但既然已经学习了本书的6 章内容,你也应该掌握一定的知识了。从现在开始,你应该逐渐学会使用目录来组织分析项目,每开始一个项目,就应该将R 的工作目录设置为与这个项目相关的目录。
还可以使用R 的命令来设置工作目录,但我们不建议使用这种方法:
setwd("/path/to/my/CoolProject")
不要使用这种操作,因为还有更好的方法,可以让你像专家一样管理与R 相关的工作。
6.3 路径与目录
路径与目录稍微有一点复杂,因为路径有2 种基本风格:Mac/Linux 和Windows。它们主要有以下3 种区别。
• 最重要的区别是如何分隔路径中的各个部分。Mac 和Linux 使用的是斜杠(如plots/diamonds.pdf),Windows 使用的则是反斜杠(如plots\diamonds.pdf)。R 支持任意一种类型(不管你现在使用的是哪种平台),但问题是,反斜杠在R 中具有特殊意义,因此,如果想要表示路径中的单个反斜杠,你需要输入2 个反斜杠!这有点令人沮丧,因此我们建议你一直使用Linux/Mac 风格的斜杠。
• 绝对路径(即不管你的工作目录是什么,都指向一个位置的路径)的形式不同。在Windows 系统中,绝对路径的开头是驱动器号(如C:)或两个反斜杠(如\servername);在Mac/Linux 系统中,绝对路径的开头则是斜杠“/”(如/user/hadley)。千万不要在脚本中使用绝对路径,因为不利于分享:没有任何人会和你具有完全相同的目录设置。
• 最后一个小区别是~ 指向的位置。~ 是指向主目录的一个很方便的快捷方式。Windows其实没有主目录的概念,因此~ 指向的是文档目录。