在本章中,我们将介绍:
- 准备分析
- 将就业数据导入 R
- 探索就业数据
- 获取和合并其他数据
- 添加地理信息
- 提取州和县一级的工资和就业信息
- 可视化薪酬的地理分布
- 按行业探索工作位置
- 地理空间时间序列的动画地图
- 对一些常见任务进行性能基准评测
该项目将向您介绍由美国政府的劳工统计局(BLS)提供的美国就业数据。 BLS 是联邦机构,负责衡量美国经济中的劳动力市场活动以及工作条件和价格。 其任务是收集,分析和传播必要的经济信息,以支持公共和私人决策。 在本项目中,我们将使用从季度就业和工资普查(QCEW)中得出的,按地理和行业分层的 2012 年就业和薪酬年度汇总数据。
可以从这个页面将这些数据下载为压缩的逗号分隔值(CSV)文件,其中包含单个文件2012.annual.singlefile.csv
。 该文件有 15 列和约 350 万行。
QCEW 是通过公司税收收集系统每季度收集的数据,这些数据与雇主报告的就业和工资有关。 这项人口普查覆盖了约 98%的美国文职工作,不包括所有人,无公司非法经营的个体经营者,无薪家庭成员以及一些农场工人和家政工人。 可以按县,大城市(MSA),州和国家/地区和行业级别作为汇总数据使用该数据。 该政府计划自 1930 年代以来已经以某种形式实施,而当前形式则自 2003 年以来一直存在。数据基于法律要求的向联邦和地方政府提交的公司报告,因此应相对不受限制。 报告偏见。 该数据汇总了按地理位置和行业划分的该国的工资和就业水平。
我们将在本章中讨论的基本问题是 2012 年美国薪资和就业的地理分布以及撰写本文时的最新可用数据。 我们将研究州和县两级,并深入探讨一些行业。 我们还将研究 2003-2012 年期间薪酬地理分布的时间变化,以及这揭示了美国就业形势的变化。
本章的目的是通过分步示例来指导您完成数据科学流程,在本例中,该示例是对美国政府 BLS 上免费提供的政府就业数据的探索。 我们将通过将数据摄取到 R 中,转换和处理数据,创建数据子集以及生成可视化效果来提供有关数据模式的一些见识的工作。 我们希望该示例可以作为另一个示例,您可以出于类似目的将其转移到其他项目。
请注意,本章中的内容比前几章更高级。
我们假设您已经阅读了第 1 章,“准备数据科学环境”,并且已经在计算机上提供了 RStudio,可用于完成本章中的配方。
本食谱将为您完成该项目所需的工具奠定基础。 如果您的计算机上未安装 R,请参阅第 1 章“准备数据科学环境”中的说明。
您需要一台装有 R 的计算机并可以连接互联网。
通过从 BLS 网站下载数据集并确保我们具有所需的 R 包,以下步骤将为您做好本章其余部分的准备:
- 从这个页面下载 76.8 MB 压缩数据,并将其保存到您会记得的位置。
- 通过在资源管理器或 finder 中右键单击文件来解压缩文件,然后使用适当的菜单项。
如果您熟悉 Linux / Mac OS X 中终端中的命令行,则可以使用unzip 2012_annual_singlefile.zip
轻松解压缩下载的文件。
- 在您的计算机上启动 RStudio IDE(对于纯粹主义者,仅启动普通 R)。
- 加载此项目所需的 R 包:
library(data.table)
library(plyr)
library(dplyr)
library(stringr)
library(ggplot2)
library(maps)
library(bit64)
library(RColorBrewer)
library(choroplethr)
如果您的计算机上没有安装这些软件包之一,则可以使用以下命令轻松安装它,将data.table
替换为要安装的软件包名称:
install.packages('data.table',repos='http://cran.r-project.org')
R 软件包存储库(称为CRAN
)在全球范围内具有多个镜像。 在这种用法中,镜像是在不同区域的服务器上运行的软件存储库的副本,从而为该位置附近的个人提供了更快的访问权限。 您可以并且应该选择在地理位置上与您的位置最近的镜子,以加快软件包的下载速度。 在前面的代码片段中,将http://cran.r-project.org
更改为首选CRAN
镜像的 URL。
- 最后,将工作目录设置为保存文件的路径。 这将告诉 R 您希望它在哪里寻找文件:
setwd('path')
我们将主要使用三个不同的 R 包,这些包在导入,操作和转换大型数据集时非常有用。
软件包data.table
改进了 R 中的data.frame
对象,从而使操作更快,并允许在数据集中指定索引变量,这是数据库专家熟悉的概念。 它还允许快速聚合大数据,包括快速排序的联接。 我们将主要使用data.table
包的fread
函数,该函数允许(非常)快速将大型结构化数据集导入 R。我们还将研究此包中的函数相对于我们在函数集中使用的其他函数的相对性能 本章后面的基准测试方法。
stringr
程序包提供了用于文本和字符串操作的工具。 该程序包简化并在语法上统一了 R 中可用的字符串操作功能,从而使涉及字符串搜索,操作和提取的任务更加容易。 我们将在这里需要这些功能。
dplyr
软件包是 Hadley Wickham 博士流行的软件包plyr
的下一个迭代。 它针对矩形数据,并允许非常快速的聚合,转换,汇总,列选择和联接。 它还提供了语法糖,以允许将命令串在一起,将一个命令的结果传递到下一个命令中。 这将是我们在该项目中的主力军。
ggplot2
软件包将成为我们可视化的主力军。 它在 R 中实现了图形语法范例,并提供了一种非常灵活的方式来创建可视化。
maps
软件包提供了我们将在可视化中使用的有关美国的地理信息。
dplyr
参考资料,包含指向小插图和其他参考资料的链接ggplot2
参考资料sqldf
参考资料
该项目的第一步是将就业数据导入 R,以便我们可以开始评估数据并进行一些初步分析。
完成上一个食谱后,您应该准备继续。
以下步骤将指导您通过两种不同的方式导入 CSV 文件:
- 我们可以使用以下命令将数据文件直接加载到 R 中(甚至是压缩版本):
ann2012 <- read.csv(unz('2012_annual_singlefile.zip',
'2012.annual.singlefile.csv'), stringsAsFactors=F)
但是,您会发现此文件花费很长时间。 有更好的方法。
- 我们选择将数据直接导入 R 中,因为我们将在以后进行进一步的操作和合并。 我们将使用
data.table
包中的fread
函数执行此操作:
library(data.table)
ann2012 <- fread('data/2012.annual.singlefile.csv')
而已。 真的! 它也比其他方法快许多倍。 默认情况下,它不会将字符变量转换为因数,因此,如果以后需要因数,则必须将其转换,在我们看来,这在任何情况下都是理想的功能。
我们从第 2 章,“通过汽车数据”驾驶视觉分析中熟悉了read.csv
。 它基本上逐行读取数据,并以逗号分隔列。 由于我们用于该项目的数据为 350 万行,因此它仍然足够小以适合大多数现代个人计算机的内存,但是使用read.csv()
导入将需要相当长的时间。
data.table
程序包中的fread
函数使用基础 C 级函数从文件中找出文件中的长度,字段数,数据类型和定界符,然后使用其参数读取文件 学到了。 结果,它比read.csv
快得多。 R 文档中有fread
的详细说明。
当前 R 中的限制之一是导入 R 中的数据需要适合主机计算机的内存。 对于大型数据集,使用基于 SQL 的数据库进行数据存储和处理会利用基于 SQL 的数据库的速度,从而规避了 R 的内存限制。 通常,在企业环境中,数据存储在 Oracle,SAP,MySQL 或 PostgreSQL 数据库中。
如果您来自 SQL 背景,sqldf
软件包将非常有用,许多进入数据科学领域的人都具有这样的背景。 该软件包允许您在 R 中使用 SQL 命令和查询,并像对待 SQL 数据库中的表一样对待 R 中的data.frame
对象。 它还允许您与您有权访问的大多数基于 SQL 的数据库进行连接,包括 SQLite,MySQL 和 PostgreSQL 等。
作为演示,我们可以将数据导入 SQLite 数据库,然后在其中读取和操作它:
sqldf('attach blsdb as new')
read.csv.sql(file='2012.annual.singlefile.csv', sql='create table main.ann2012 as select * from file', dbname='blsdb')
ann2012 <- sqldf("select * from main.ann2012", dbname='blsdb')
您必须在计算机上安装并可用 SQLite 才能使上述代码起作用。 我们将把安装工作留给您。
这也将花费一些时间,但是您将在 SQLite 中获得数据。 前面的命令实际上并不将数据摄取到 R 中,而只是将其导入到 SQLite 中。
您可以使用以下命令将数据导入 R:
ann2012 <- sqldf("select * from main.ann2012", dbname='blsdb')
您还可以选择使用sqldf
在 SQLite 中使用 SQL 进行操作。 对于某些用户来说,使用 SQL 操作数据然后将导入的数据仅导入 R 会更容易。
由于本书的第一部分专注于 R,因此我们不会在这里介绍的内容之外更深入地研究sqldf
的使用。 但是,如果您对 SQL 更加熟悉,欢迎您使用 SQL 命令在各种配方中复制 R 中介绍的步骤。
现在将数据导入到 R 中,并且我们已经学习了一些将较大的数据集导入到 R 中的策略,我们将对数据进行一些初步分析。 目的是查看数据的外观,识别特质,并确保其余的分析计划可以继续进行。
如果您完成了最后一个食谱,则应该准备好了。
以下步骤将引导您完成本食谱,以探索数据:
- 首先,让我们看看这些数据有多大:
> dim(ann2012)
[1] 3556289 15
很好,只有15
列。
- 让我们看一下前几行,以便我们可以看到数据是什么样的:
head(ann2012)
您可以参考以下屏幕截图:
什么是变量own_code
**
,**
industry_code
等,它们是什么意思? 我们可能需要更多数据才能理解此数据。
- 在这些数据中还有一个怪异的特质。
total_annual_wages
,taxable_annual_wages
和annual_contributions
的某些值看起来很小。 实际数据显示,这些数字似乎不正确。 但是,fread
实际上可以指示正在发生的事情:
ann2012 <- fread('data/2012.annual.singlefile.csv', sep=',',
colClasses=c('character', 'integer', 'integer', 'integer',
'integer', 'integer', 'character',rep('integer',8)))
您可以参考以下屏幕截图:
- 这指出了以下事实:可能需要
bit64
程序包才能正确显示这些大数字。 安装并加载此程序包,然后重新导入数据可解决此问题,如以下命令行所示:
install.packages('bit64')
library('bit64')
ann2012 <- fread('data/2012.annual.singlefile.csv', sep=',',
colClasses=c('character', 'integer', 'integer', 'integer',
'integer', 'integer', 'character',rep('integer',8)))
您可以参考以下屏幕截图:
head
命令显示数据帧的前几行(默认为前六行)。 我们注意到,有些标题是不言自明的,但有些则暗示了我们当前无法访问的代码。 我们将必须获取其他数据才能进行有意义的分析。 我们可以查看数据而无需将其导入 R。UNIX 命令less
和 Windows PowerShell 命令type
可以向我们展示与head
相同的内容。
- 请参阅这个页面上可用数据集的文档。
在上一个配方中,我们发现需要其他数据来了解 CSV 文件中的数据实际代表什么,并且该配方将直接解决此需求。
我们可以在 BLS 网站的标题 Associated Codes and Titles
下找到其他数据。 那里有五个文件,我们将其下载到我们的计算机中。 它们如下:
我们将它们下载到我们的计算机上,记住它们的存储位置。 我们需要准备将它们导入 R 并将它们与我们的原始数据合并。
以下步骤将引导您将这些文件加载到 R 中,并将它们连接到更大的数据框中:
- 现在,我们将使用以下命令行将这些数据文件导入 R:
for(u in c('agglevel','area','industry','ownership','size')){
assign(u,read.csv(paste('data/',u,'_titles.csv',sep=''),stringsAsFactors=
F))
}
这是一个代码示例,使我们可以更轻松地执行重复任务。
- 每个数据集都有一个与我们的原始数据
ann2012
相同的变量(列标题),如以下屏幕快照所示:
- 因此,将数据集组合在一起应该相当容易。 现在,我们将其中四个数据集与
ann2012
结合起来,并保存area
,即area_titles.csv
的数据用于下一个配方,因为我们想对它进行一些操作:
codes <- c('agglevel','industry','ownership','size')
ann2012full <- ann2012
for(i in 1:length(codes)){
eval(parse(text=paste('ann2012full <- left_join(ann2012full, ',codes[i],')', sep='')))
}
最终结果显示在以下屏幕截图中:
在如何操作... 部分的步骤 1 中,我们想将每个数据集分配给它自己的对象。 我们可以为每次导入编写一行代码,但是此代码使我们可以更快地执行此操作,并且将来将更易于维护。 assign
命令具有两个基本输入:变量名称和要分配给变量名称的值。 这里的for
循环不会遍历数字,而是遍历对象。 在第一次迭代中,u
取值agglevel
。 assign
函数的名称为agglevel
,并为其分配read.csv
命令的结果。 在paste
命令中,我们再次使用u
的值,因为我们要导入的所有文件都具有相同的命名约定。 正是这种通用的命名约定使我们能够使用这种类型的编码。 因此,第一次迭代给出了assign('agglevel', read.csv('data/agglevel_title.csv'))
,
等。
在步骤 2 中,我们将数据集连接在一起。 我们首先将原始数据复制到新名称ann2012full
,以便我们可以建立新数据集而不会在出现问题的情况下不破坏原始数据。 然后,我们使用类似于宏的构造将所有新数据集连接到原始数据集,并在for
循环中的数字和向量代码的索引上进行迭代。
让我们从这个复杂的命令(从总体上理解复杂代码的一种明智的策略)着手进行研究。 在paste
命令中,我们创建要评估的命令。 我们想要做一个left_join
(来自dplyr
包),在第一次迭代中将ann2012full
与agglevel
结合在一起。 left_join
确保保留ann2012full
的所有行,并适当地复制agglevel
的行以匹配ann2012full
中的行数。 由于两个数据集中只有一个公共变量,因此left_join
会自动选择使用此变量进行联接。
通常,left_join
将使用在两个数据集中发现的所有变量名称将两个数据集连接起来。 如果您不想这样做,则可以通过指定例如left_join(ann2012full, agglevel, by="agglvl_code ").
来指定要用于联接的变量。
然后,eval
语句评估我们使用paste
命令构造的命令。 我们遍历代码中的名称,以便使四个数据集的每个都与ann2012full
结合在一起。
快速检查将显示联接之后ann2012full
中的行数与ann2012
中的行数相同。
本章的主要目的是研究全美工资的地理分布。 对此进行映射需要我们首先拥有一张地图。 幸运的是,maps
软件包中提供了州和县两级的美国地图,并且可以提取制作这些地图所需的数据。 我们将本食谱中的就业数据与地图数据对齐,以便在地图上的正确位置显示正确的数据。
我们已经将area
数据集导入到 R 中,因此可以开始使用了。
以下步骤将指导您完成在 R 中创建第一个地图的过程:
- 我们首先来看
area
中的数据:
head (area)
输出显示在以下屏幕截图中:
我们看到这里有一个叫做area_fips
的东西。 人口普查局使用联邦信息处理标准(FIPS)代码来指定美国的县和其他地理区域。
- 根据约定,我们希望将所有名称都大写。 我们将编写一个小函数来做到这一点:
simpleCap <-function(x){
if(!is.na(x)){
s <- strsplit(x,' ')[[1]]
paste(toupper(substring(s,1,1)), substring(s,2), sep='', collapse=' ')
} else {NA}
}
maps
程序包包含两个我们将要使用的数据集; 它们是county.fips
和state.fips
。 我们将首先进行一些转换。 如果我们查看county.fips
,我们会注意到 FIPS 代码在某些代码的左侧缺少前导0
。 我们的就业数据中的所有代码均由五位数字组成:
> data(county.fips)
> head(county.fips)
fips polyname
1 1001 alabama,autauga
2 1003 alabama,baldwin
3 1005 alabama,barbour
4 1007 alabama,bibb
5 1009 alabama,blount
6 1011 alabama,bullock
stringr
软件包将在这里为我们提供帮助:
county.fips$fips <- str_pad(county.fips$fips, width=5, pad="0")
- 我们要从
county.fips
的polyname
列中分离县名。 我们将在一分钟内从state.fips
获取状态名称:
county.fips$polyname <- as.character(county.fips$polyname)
county.fips$county <- sapply(
gsub('[a-z\ ]+,([a-z\ ]+)','\\1',county.fips$polyname), simpleCap)
county.fips <- unique(county.fips)
state.fips
数据涉及很多细节:
> data(state.fips)
输出显示在以下屏幕截图中:
- 如有必要,我们将再次在
fips
列上填充0
,以便它们有两位数字,并从polyname
中使用州名称大写以创建新的state
列。 该代码类似于我们用于county.fips
数据的代码:
state.fips$fips <- str_pad(state.fips$fips, width=2, pad="0", side='left')
state.fips$state <- as.character(state.fips$polyname)
state.fips$state <- gsub("([a-z\ ]+):[a-z\ \\']+",'\\1',state.fips$state)
state.fips$state <- sapply(state.fips$state, simpleCap)
- 我们确保我们有唯一的行。 我们在这里需要小心,因为我们只需要在
fips
和state
值中具有唯一性,而不需要在其他代码中具有唯一性:
mystatefips <-unique(state.fips[,c('fips','abb','state')])
unique
函数应用于data.frame
对象时,将返回该对象的唯一行。 您可能习惯于在单个向量上使用unique
查找向量中的唯一元素。- 我们得到低 48 个州名称的列表。 我们将过滤数据以仅查看以下状态:
lower48 <- setdiff(unique(state.fips$state),c('Hawaii','Alaska'))
setdiff
设置操作将查找第一组中所有不在第二组中的元素。
- 我们将所有这些信息放到一个单独的数据集
myarea
中:
myarea <- merge(area, county.fips, by.x='area_fips', by.y='fips', all.x=T)
myarea$state_fips <- substr(myarea$area_fips, 1,2)
myarea <- merge(myarea, mystatefips,by.x='state_fips',by.y='fips', all.x=T)
- 最后,我们将地理信息与数据集结合在一起,并对其进行过滤,以仅将数据保留在较低的 48 个州中:
ann2012full <- left_join(ann2012full, myarea)
ann2012full <- filter(ann2012full, state %in% lower48)
- 现在,我们将最终数据集存储在磁盘上的 R 数据(
rda
)文件中。 这为 R 对象提供了一种有效的存储机制:
save(ann2012full, file='data/ann2014full.rda',compress=T)
该食谱的 12 个步骤涵盖了相当多的内容,因此,从第 2 步开始,让我们深入研究一些细节。simpleCap
函数是 R 中一个函数的示例。我们使用函数封装重复的任务,从而减少了 代码重复,并确保错误具有单一起源。 如果仅重复代码,手动更改输入值,我们就很容易在转录中犯错误,破坏隐藏的假设或意外覆盖重要变量。 此外,如果要修改代码,则必须在每个重复的位置手动进行。 这很繁琐且容易出错,因此我们创建函数,这是我们强烈鼓励您遵循的最佳实践。
simpleCap
功能使用三个功能:strsplit, toupper
和substring
。 每当strsplit
函数发现要分割的字符串片段(在我们的情况下为' '
或空格)时,它都会分割字符串(或字符串向量)。 substring
函数从指定的字符位置之间的字符串中提取子字符串。 仅指定一个字符位置意味着从该位置提取到字符串的末尾。 toupper
函数将字符串的大小写从小写更改为大写。 反向操作由tolower
完成。
从步骤 3 开始,程序包通常将示例数据与它们捆绑在一起。 county.fips
和state.fips
是已捆绑到maps
程序包中的数据集的示例。
步骤 4 中使用的stringr
程序包是 Wickham 博士提供的另一种程序包,它提供字符串操作功能。 在这里,我们使用str_pad
,它用字符(此处为0
)填充字符串,以为字符串提供特定的宽度。
在第 5 步中,我们使用 R 中的内置正则表达式(regex)功能。在这里,我们不会过多地讨论正则表达式。 gsub
函数查找第一个模式,并将第二个模式替换为指定为第三个字符串。 在这里,我们要寻找的模式包括一个或多个字母或空格([a-z\ ]+)
,
,然后是逗号,然后是一个或多个字母或空格。 我们要保留第二组字母和空格,因此我们在其周围加上括号。 1
模式表示将整个模式替换为我们用括号括起来的第一个模式。 此替换发生在polyname
字段的每个元素上。
由于我们希望对polyname
中的每个元素都使用大写字母,因此可以使用for
循环,但是可以选择使用效率更高的sapply
。 polyname
中的每个元素都通过simpleCap
函数传递,因此在步骤 7 中被大写。
在步骤 10 中,我们将area
,county.fips
和mystatefips
数据集连接在一起。 我们使用merge
函数而不是left_join
函数,因为我们要加入的变量对于不同的data.frame
对象具有不同的名称。 R 标准库中的merge
函数提供了这种灵活性。 为了确保左连接,我们指定all.x=TRUE
。
在步骤 11 中,我们将myarea
数据框连接到我们的ann2014full
数据集。 然后,我们使用 filter
函数对数据进行子集处理,将其限制为来自较低 48 个州的数据。 filter
功能来自dplyr
程序包。 在下一个食谱中,我们将讨论dplyr
中的功能。
到目前为止,我们一直在努力使数据成形以进行分析。 现在,我们开始研究每个州和每个县的平均年薪的地理分布。
如果到目前为止,您已经完全按照本章中的说明进行操作,则将以表格的形式获取数据,从中可以提取不同级别的信息。 我们很高兴去!
我们将首先在状态级别从ann2014full
提取数据。 我们需要执行以下步骤:
- 我们来看
aggregate
状态级别的数据。 窥视agglevel
会告诉我们,所需数据级别的代码是50
。 此外,我们只希望查看平均年薪(avg_annual_pay)
和平均年就业水平(annual_avg_emplvl)
,而不要查看其他变量:
d.state <- filter(ann2014full, agglvl_code==50)
d.state <- select(d.state, state, avg_annual_pay, annual_avg_emplvl)
- 我们创建了两个新变量
wage
和empquantile,
,它们离散化了pay
和employment
变量:
d.state$wage <- cut(d.state$avg_annual_pay,
quantile(d.state$avg_annual_pay, c(seq(0,.8, by=.2), .9, .95, .99, 1)))
d.state$empquantile <- cut(d.state$annual_avg_emplvl,
quantile(d.state$annual_avg_emplvl, c(seq(0,.8,by=.2),.9,.95,.99,1)))
- 我们还希望这些离散变量的级别有意义。 因此,我们运行以下命令:
x <- quantile(d.state$avg_annual_pay, c(seq(0,.8,by=.2),.9, .95, .99, 1))
xx <- paste(round(x/1000),'K',sep='')
Labs <- paste(xx[-length(xx)],xx[-1],sep='-')
levels(d.state$wage) <- Labs
x <- quantile(d.state$annual_avg_emplvl, c(seq(0,.8,by=.2),.9, .95, .99, 1))
xx <- ifelse(x>1000, paste(round(x/1000),'K',sep=''),round(x))
Labs <- paste(xx[-length(xx)],xx[-1],sep='-')
levels(d.state$empquantile) <- Labs
获得 0、0.2、0.4、0.6、0.8、0.9、0.95、0.99 和 1 个分位数的年平均薪水,然后按千分之一获得。 然后重复执行该任务,以实现年度平均就业率。
- 我们在县一级重复此过程。 我们将发现适当的聚合级别代码为 70(
agglvl_code==70
)。 其他一切都一样。 这次让我们变得更加聪明。 首先,我们将以相同的方式离散化变量,然后更改标签以使其匹配。 函数可能是个好主意! 以下命令行对此进行了描述:
Discretize <- function(x, breaks=NULL){
if(is.null(breaks)){
breaks <- quantile(x, c(seq(0,.8,by=.2),.9, .95, .99, 1))
if (sum(breaks==0)>1) {
temp <- which(breaks==0, arr.ind=TRUE)
breaks <- breaks[max(temp):length(breaks)]
}
}
x.discrete <- cut(x, breaks, include.lowest=TRUE)
breaks.eng <- ifelse(breaks > 1000,
paste0(round(breaks/1000),'K'),
round(breaks))
Labs <- paste(breaks.eng[-length(breaks.eng)], breaks.eng[-
1],
sep='-')
levels(x.discrete) <- Labs
return(x.discrete)
}
- 我们之前提到过
dplyr
的句法糖。 现在,我们看到了它的作用。dplyr
包允许您使用**
%.%**
运算符将不同的操作组合在一起,将一个操作的结果作为下一个输入的管道。 我们将在下一个食谱中描述dplyr
的主要操作。 通过使用一些函数封装,以下代码实现了我们花费大量代码才能在1-3
步骤中实现的所有功能:
d.cty <- filter(ann2012full, agglvl_code==70)%.%
select(state,county,abb, avg_annual_pay, annual_avg_emplvl)%.%
mutate(wage=Discretize(avg_annual_pay),
empquantile=Discretize(annual_avg_emplvl))
现在,我们有了可视化数据中地理图案所需的基本数据集。
前面的五个步骤涵盖了很多 R 代码,因此让我们开始进行分解。 filter
和select
这两个功能来自dplyr
。 dplyr
程序包提供了五个基本功能,如下所示:
filter
:这将根据指定的条件创建数据的子集select
:这从数据集中选择列或变量mutate
:这将在数据集中创建新列或变量,这些新列或变量是从数据集中的其他变量派生的group_by
:这将数据按一个变量或一组变量拆分,随后的功能将对由唯一变量值或组合定义的每个组件进行操作arrange
:这将根据数据集中的变量重新排列(或排序)数据
这些功能中的每一个都可以对dplyr
的一部分data.frame
,data.table
或tbl
对象进行操作。
cut
函数根据指定的断点或阈值离散化连续变量。 在这里,我们根据变量的分位数指定阈值。 我们通过分数序列指定所需的分位数:
c(seq(0, .8, by=.2), .9, .95, .99, 1)
使用seq
函数可以创建规则的数字序列,其起始值,终止值以及两个连续值之间的差。
在第 3 步中,我们采用指定的阈值并对它们进行格式化。 如通常所见,大于 1,000 的数字将在数千个位置被截断并附加K
。 在未指定小数位数的情况下使用round
表示没有小数位数。
此外,在第 3 步中,我们希望标签代表一个范围。 因此,我们需要通过在格式阈值的连续值之间放置一个破折号(-
)来创建标签。 一种方法是创建阈值向量的两个副本,一个副本不包含最后一个元素,另一个不包含第一个元素。 然后,将它们与-
粘贴在一起。 请注意,此技巧允许将连续的阈值对齐并粘贴在一起。 如果您不确定,请打印xx[-length(xx)]
和xx[-1]
并亲自查看。
Discretize
函数封装了我们在离散结果和格式化标签方面所做的工作。
此代码段使用dplyr
的语法将功能串在一起。 我们首先对原始数据进行子集处理,仅保留具有agglvl_code=50
的数据(请注意代码中的==
)。 然后,我们将生成的缩减数据通过管道传递到第二个函数select
中,该函数仅保留我们感兴趣的四个变量。这进一步缩减了数据,然后将其输入到mutate
函数中,然后该函数创建了两个新的 数据对象中的变量。 然后,该最终对象与变量名d.cty
一起存储。
我们创建了数据集,其中包含我们需要可视化各县和州的平均工资和就业情况的数据。 在本食谱中,我们将通过使用映射到特定值或值范围的颜色来阴影化地图的适当区域,从而可视化薪酬的地理分布。 这通常称为叶绿素图; 在过去的几年中,这种可视化类型变得越来越流行,因为制作这样的地图变得更加简单,尤其是在线制作。 其他地理可视化将覆盖标记或其他形状来表示数据; 无需用地理上有意义的边界填充特定形状。
在完成最后一个配方后,您应该准备使用我们创建的数据集来可视化地理分布。 我们将使用ggplot2
包来生成我们的可视化文件。 我们还将使用RColorBrewer
程序包,该程序包提供视觉上有吸引力的调色板。 如果您目前没有RColorBrewer
,请使用install.packages('RColorBrewer', repos='http://cran.r-project.org')
进行安装。
以下步骤将引导您完成此地理空间数据可视化的创建:
- 我们首先需要在地图上获取一些数据。
ggplot2
软件包提供了一个方便的功能map_data
,用于从maps
软件包中捆绑的数据中提取该函数:
library(ggplot2)
library(RColorBrewer)
state_df <- map_data('state')
county_df <- map_data('county')
- 现在,我们进行一些转换以使此数据与我们的数据一致:
transform_mapdata <- function(x){
names(x)[5:6] <- c('state','county')
for(u in c('state','county'){
x[,u] <- sapply(x[,u],simpleCap)
}
return(x)
}
state_df <- transform_mapdata(state_df)
county_df <- transform_mapdata(county_df)
data.frame
对象state_df
和county_df
包含点的纬度和经度。 这是我们的主要图形数据,需要将它与我们在上一个配方中创建的数据结合起来,其中包含有效的地图颜色信息:
chor <- left_join(state_df, d.state, by='state')
ggplot(chor, aes(long,lat,group=group))+
geom_polygon(aes(fill=wage))+geom_path(color='black',size=0.2) + scale_fill_brewer(palette='PuRd') + theme(axis.text.x=element_blank(),
axis.text.y=element_blank(), axis.ticks.x=element_blank(),
axis.ticks.y=element_blank())
这使我们得到下图,该图描述了各州的平均年薪分布:
- 我们可以类似地创建县平均年薪的可视化,这将为我们提供有关工资的地理分布的更详细的信息:
chor <- left_join(county_df, d.cty)
ggplot(chor, aes(long,lat, group=group))+
geom_polygon(aes(fill=wage))+
geom_path( color='white',alpha=0.5,size=0.2)+
geom_polygon(data=state_df, color='black',fill=NA)+
scale_fill_brewer(palette='PuRd')+
labs(x='',y='', fill='Avg Annual Pay')+
theme(axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks.x=element_blank(), axis.ticks.y=element_blank())
这产生了下图,显示了各县平均年薪的地理分布:
从上图可以明显看出,北达科他州西部,怀俄明州和内华达州西北部都有高薪工作,这很可能是由这些地区新的石油勘探机会推动的。 更明显的城市和沿海地区也表现得很好。
让我们深入了解前面 4 个步骤的工作原理。 ggplot2
提供map_data
功能,以从maps
包中提取地图数据。 除了县和州以外,它还可以提取由[...] maps
软件包。
county_df
和state_df
中包含州和县信息的列最初被命名为region
和subregion
。 在第 2 步中,我们需要将其名称分别更改为state
和county
,以使将这些数据与我们的就业数据结合起来更加容易。 我们还使用州和县的名称大写,以符合格式化employment
数据集中数据的方式。
为了在第 3 步中创建地图,我们通过使用州名将state_df
和d.state
连接起来来创建绘图数据集。 然后,我们使用ggplot
绘制美国地图,并在每个州中填入与以前的食谱中创建的工资水平和离散化的平均年薪相对应的颜色。 详细地说,我们确定该图的数据来自chor
,并根据每个州的边界的经度和纬度绘制多边形(geom_polygon
),并根据工资的高低用一种颜色填充它们 ,然后以黑色绘制状态的实际边界(geom_path
)。 我们指定我们将使用从白色开始,经过紫色和具有对应于最高工资水平的红色的调色板。 通过指定标签并从图中删除轴注释和刻度来格式化其余代码。
对于第 4 步,代码与第 3 步基本相同,除了我们为县(而非州)的边界绘制多边形。 除了白色的县界以外,我们还添加了一层以黑色(geom_polygon(data=state_df, color='black', fill=NA)
)绘制州界。
- 请参阅这个页面
在前面的食谱中,我们看到了如何可视化薪酬的顶级汇总数据。 就业数据集具有更细粒度的数据,按公共/私营部门和工作类型划分。 该数据中的作业类型遵循称为北美行业分类系统(NIACS)的分层编码系统。 在本食谱中,我们将考虑四个特定行业,并以可视化方式查看这些行业的就业地理分布,仅限于私营部门的工作。
我们将在此配方中研究四个工业部门:
- 农业,林业,渔业和狩猎业(NIACS 11)
- 采矿,采石与油气开采(NIACS 21)
- 金融和保险(NIACS 52)
- 专业技术服务(NIACS 54)
我们需要执行以下步骤来创建就业数据的子集,包括工业部门的数据,但将其限制为私营部门:
- 我们首先根据对行业和私营部门施加的条件过滤数据,并仅保留相关变量:
d.sectors <- filter(ann2012full, industry_code %in% c(11,21,54,52),
own_code==5, # Private sector
agglvl_code == 74 # county-level
) %.%
select(state,county,industry_code, own_code,agglvl_code,
industry_title, own_title, avg_annual_pay,
annual_avg_emplvl)%.%
mutate(wage=Discretize(avg_annual_pay),
emplevel=Discretize(annual_avg_emplvl))
d.sectors <- filter(d.sectors, !is.na(industry_code))
在这里,我们的选择基于一组行业规范,并且我们将自己限于县级数据。 该代码与以前不同,因为我们现在正在查看行业特定的数据。
- 现在,我们使用
ggplot2
创建可视化。 该可视化将由四个面板组成的阵列,每个工业部门一个。 每个面板上都会有美国的县级地图,上面的颜色表示每个特定行业在 2012 年每个县的就业水平。 我们还将为此可视化选择一个蓝色为主的调色板:
chor <- left_join(county_df, d.sectors)
ggplot(chor, aes(long,lat,group=group))+
geom_polygon(aes(fill=emplevel))+
geom_polygon(data=state_df, color='black',fill=NA)+
scale_fill_brewer(palette='PuBu')+
facet_wrap(~industry_title, ncol=2, as.table=T)+
labs(fill='Avg Employment Level',x='',y='')+
theme(axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks.x=element_blank(),
axis.ticks.y=element_blank())
这将产生以下可视化效果,显示按行业划分的就业分布:
在此配方中,我们将dplyr
函数用于数据munging
。 我们的过滤条件之一是 industry_code
变量应具有11
,21
,52
或54
中的值之一。 这是通过%in%
操作员完成的,它是一种设置操作。 它询问左侧的元素是否是右侧集合的成员。 filter
语句中有多个条件,以逗号分隔。 这意味着AND
关系,必须满足所有标准才能使数据通过过滤器。
我们注意到行业代码中缺少一些值。 这在可视化中产生了一个额外的面板,与缺少行业代码的数据相对应。 我们不想这样做,因此我们在第一步中过滤掉了这些数据。
在第二步中,用于创建可视化的命令与上一配方基本相同,但以下几行除外:
facet_wrap(~industry_title, ncol=2)
此命令按industry_title
的值拆分数据,为industry_title,
的每个值创建单独的可视化文件,然后将它们放回具有两列和适当数量的行的网格中。 我们还在此处使用了industry_title
而不是 industry_code
(它们具有相同的可视化效果),这样面板的标签是可以理解的,而不是仅包含一些需要读者看的数字 他们的意思。
此食谱是此数据集的冰山一角。 从私营/公共部门以及深入到不同行业的角度来看,可以使用此数据探索许多层次。 还可以提供 2012 年的其他季度数据,这些数据可以阐明时间模式。 从 1990 年起可以获取年度和季度数据。 通过将就业的时间模式与其他社会经济事件相关联,可以进行进一步的分析。 choroplethr
和rMaps
包提供了为这种类型的数据随时间创建动画的方法。
- 在这个页面和这个页面中了解有关
rMaps
程序包的信息 - 有关
choroplethr
软件包的信息 - 查看
choropleth
挑战结果 - 查看动画地图的示例
该项目的真正兴趣之一是了解工资模式(作为收入模式的替代)如何随时间变化。 QCEW 网站提供了 2003 年至 2012 年的数据。在此配方中,我们将查看这些年份每年各县的总体平均年薪,并创建一个动画显示该时期薪资模式的变化。
对于此食谱,我们需要从 BLS 网站(HTG4)http://www.bls.gov/cew/datatoc.htm 下载 2003 至 2011 年的年度数据。 您需要在CSVs Single Files-Annual Averages
列中下载与这些年份相对应的基于 QCEW NIACS 的数据文件。 将这些文件(它们是压缩的.zip
文件)存储在与在此项目开始时下载的压缩 2012 数据相同的位置。 不要解压缩它们! 如果尚未安装,则还必须使用install.packages('chloroplethr')
下载并安装choroplethr
软件包。
请注意,此配方相对来说会占用大量内存。 在 32 位计算机上运行的计算机可能会遇到内存不足的问题。
我们需要做的是导入从 2003 年到 2012 年的所有年份的数据,并提取每个县的县级(agglvl_code==70
)平均年薪(avg_annual_pay
)的数据,将其绘制出来,然后将薪水字符串化 值一起在动画中显示。 由于我们基本上需要对每年的数据执行相同的操作,因此可以在for
循环中执行此操作,并且可以创建函数来封装重复的操作。 我们首先编写一年的代码,然后执行以下步骤:
- 我们从这个原型代码中称为
zipfile
的 ZIP 文件中导入数据。 实际上,文件名的格式为2003_annual_singlefile.zip
,而其中的 CSV 文件的格式为2003.annual.singlefile.csv
。 我们将使用代码中 ZIP 和 CSV 文件中的常见模式来自动执行该过程。 对我来说,数据位于一个名为data
的文件夹中,该文件夹反映在以下代码中:
unzip(file.path('data',zipfile), exdir='data') # unzips the file
csvfile <- gsub('zip','csv', zipfile) # Change file name
csvfile <- gsub('_','.',csvfile) # Change _ to . in name
dat <- fread(file.path('data', csvfile)) # read data
- 现在,我们将就业数据与
myarea
中的地理数据结合起来:
dat <- left_join(dat, myarea)
- 然后,我们使用
dplyr
函数提取县级汇总工资数据,并保留州和县的信息:
dat <- filter(dat, agglvl_code==70) %.% # County-level aggregate
select(state, county, avg_annual_pay) # Keep variables
- 然后,我们将步骤 1 到步骤 3 中的动作封装在一个函数中:
get_data <- function(zipfile){
unzip(file.path('data',zipfile), exdir='data') # unzips the file
csvfile <- gsub('zip','csv', zipfile) # Change file name
csvfile <- gsub('_','.',csvfile) # Change _ to . in name
dat <- fread(file.path('data', csvfile)) # read data
dat <- left_join(dat, myarea)
dat <- filter(dat, agglvl_code==70) %.% # County-level aggregate
select(state, county, avg_annual_pay) # Keep variables
return(dat)
}
- 我们现在必须在 10 年中的每一年都重复一次,并存储数据。 对于这种类型的数据,通常使用列表对象:
files <- dir('data', pattern='annual_singlefile.zip') # file names
n <- length(files)
dat_list <- vector('list',n) # Initialize the list
for(i in 1:n){
dat_list[[i]]<- get_data(files[i]) # ingest data
names(dat_list)[i] <- substr(files[i],1,4) #label list with years
}
- 接下来,我们开始创建可视化。 由于我们实际上是在创建 10 个可视化效果,因此为了比较起见,颜色在所有颜色上都必须表示相同的含义。 因此,多年来离散化必须相同:
annpay <- ldply(dat_list) # puts all the data together
breaks <- quantile(annpay$avg_annual_pay,
c(seq(0,.8,.2),.9,.95,.99,1)) # Makes a common set of breaks
- 我们将使用相同的间隔为每年创建相同的可视化。 让我们为要生成的常见可视化创建一个函数。 我们将使用
ggplot2
进行可视化。 输入值是我们使用get_data
创建的数据,输出是可以创建可视化效果的plot
对象:
mychoro <- function(d, fill_label=''){
# d has a variable "outcome" that
# is plotted as the fill measure
chor <- left_join(county_df, d)
plt <- ggplot(chor, aes(long,lat, group=group))+
geom_polygon(aes(fill=outcome))+
geom_path(color='white',alpha=0.5,size=0.2)+
geom_polygon(data=state_df, color='black',fill=NA)+
scale_fill_brewer(palette='PuRd')+
labs(x='',y='', fill=fill_label)+
theme(axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks.x=element_blank(),axis.ticks.y=element_blank())
return(plt)
}
- 现在,我们每年使用
for
循环创建plot
对象。 我们将这些对象存储在列表中,每个元素对应于每年。 在此过程中,我们使用公共休息时间创建了一个新变量outcome
,它是离散化的薪水变量。 由于我们设计mychoro
函数的方式,因此需要将此变量称为outcome
:
plt_list <- vector('list',n)
for(i in 1:n){
dat_list[[i]] <- mutate(dat_list[[i]],
outcome=Discretize(avg_annual_pay,breaks=breaks))
plt_list[[i]] <-
mychoro(dat_list[[i]])+ggtitle(names(dat_list)[i])
}
choroplethr
程序包具有实用程序功能choroplethr_animate
,该功能可获取使用ggplot2
创建的plot
对象的列表,并制作一个带有动画 GIF 的网页,对我们在其中创建的绘图进行分层 命令。 默认的 Web 文件是animated_choropleth.html
:
library(choroplethr)
choroplethr_animate(plt_list)
我们从此处的动画中提取三个面板,以使您了解动画的外观:
即使从有限的数据角度来看,我们也可以看到北达科他州西部,怀俄明州和内华达州东北部的就业和财富显着增长,这可能是由于该地区的页岩油的发现,勘探和开采所致。 我们还可以看到,总体来说,在此显示的八年中,全国各地的薪水都在上涨; 但是,在此期间,美国大陆中部地区的平均工资几乎没有变化。 我们还在加利福尼亚州和东北部看到高薪的明显增加和扩展。 回想一下,所有三个图都在相同的色标上,因此,它们之间的解释是一致的。
我们在先前的食谱中介绍了此食谱中使用的各个功能,因此我们将不再重复。 但是,从这里看大图可以为我们指出两个要点。 首先,我们必须多次执行一组通用步骤才能创建单个图像。 由于我们必须执行相同的步骤来创建最终动画中使用的每个图像,因此我们开始对代码进行一些操作,将重复的代码块重构为功能。
其次,创建每个图像所需的一组步骤是数据科学流水线各阶段的又一例证。 在第一阶段,我们通过摄取 CSV 文件来获取数据。 我们对数据集的理解已建立在先前的配方中,因此探索和理解阶段(管道的第 2 阶段)有点轻松。 我们加入了不同的数据集,并对其进行了过滤,以进入第 3 阶段,即纠缠,争吵和操纵阶段。 对于第 4 阶段,分析和建模,我们只需要离散化数据,然后将其映射到特定但一致的色标即可。 最后,最终的数据产品,动画的整体速度,用于以简明易懂的方式传达大量数据。
R 程序包choroplethr
可以使用choropleth
函数直接使用ggplot2.
创建单个的弦乐。但是,我们不喜欢输出的默认外观,并且直接使用ggplot2
可以更轻松地进行自定义。
流行的 rCharts
程序包的创建者 Vaidyanathan 博士也创建了rMaps
程序包。 它使用 JavaScript 可视化库从 R 中创建了鹅卵石,以便在 Web 上进行演示,还可以使用ichoropleth.
函数创建动画的鹅卵石。但是,在编写本文时,该包仍在开发中,因此我们没有该功能 创建县级地图。 在这个页面的rMaps
博客中显示了具有状态级别映射的示例。
R 及其程序包生态系统通常提供执行相同任务的几种替代方法。 R 还促进用户为特定任务创建自己的功能。 当执行时间很重要时,基准测试性能是必要的,以查看哪种策略最有效。 在本食谱中,我们将专注于速度。 我们将要看的两个任务是将数据加载到 R 中,并基于一个公共变量连接两个数据对象。 所有测试都是在运行 2.4 GHz Intel 处理器,8 GB RAM 的 Windows 7 台式机上完成的。
我们将在此处使用ann2012full
和industry
数据对象进行性能实验,并使用 2012 年度就业数据 CSV 文件进行数据加载。 既然您已经拥有了这些,那么您就很好了。 如果不这样做,则需要使用install.packages()
命令安装rbenchmark
和microbenchmark
这两个功能。
以下步骤将引导我们逐步完成 R 中两个不同任务的基准测试:
- 我们的首要任务是将雇佣数据加载到 R 中。
2012.annual.singlefile.csv
文件包含 3,556,289 行数据和 15 列。 在本章中使用fread
时,还有许多其他可能的方法可以导入此数据,如下所示:
第一种也是最标准的方法是使用read.csv
读取 CSV 文件。 您也可以即时解压缩原始2012_annual_singlefile.zip
数据文件,并使用read.csv
读取数据。 我们可以在第一次加载数据时将数据保存到RData
文件中,然后在以后加载此文件时也可以将数据导入 R 中
- 基准速度的最基本方法是使用
system.time
函数,该函数测量要执行的任务所花费的时间(经过的时间和实际的计算时间):
> system.time(fread('data/2012.annual.singlefile.csv'))
user system elapsed
14.817 0.443 15.23
请注意,您看到的时间将不同于前面命令中列出的时间。
- 但是,R 中有一些软件包可以使基准测试和比较不同功能变得更加容易。 我们将介绍
rbenchmark
程序包,该程序包提供benchmark
功能,该功能允许同时比较不同的功能:
library(rbenchmark)
opload <- benchmark(
CSV=read.csv('data/2012.annual.singlefile.csv',
stringsAsFactors=F),
CSVZIP=read.csv(unz('data/2012_annual_singlefile.zip',
'2012.annual.singlefile.csv'), stringsAsFactors=F),
LOAD = load('data/ann2012full.rda'),
FREAD = fread('data/2012.annual.singlefile.csv'),
order='relative', # Report in order from shortest to longest
replications=5
)
您可以参考以下屏幕截图,获取上述命令的输出:
请注意,结果是有序的,并且相对时间记录在relative
列下。 这表明fread
比使用read.csv
读取要快得多。 有趣的是,平均而言,它比从RData
文件加载数据快四倍,后者是 R 数据的常用存储方法。 使用fread
从文件加载数据显然比以 R 自己的序列化格式存储数据要快!
- 我们的第二个任务是执行两个数据对象的左外部联接。 我们将看一下已经执行的任务-雇佣数据与行业代码的左连接。 左联接确保操作的左上的数据行将通过该操作保留,而其他数据将通过重复或丢失数据扩展为具有相同的行数。 我们在本章中使用了
left_join
,但是我们可以采用以下三种其他策略:- R 的标准库中的
merge
函数 plyr
程序包中的join
功能data.table
包中的merge
函数,首先将数据转换为data.table
对象
- R 的标准库中的
- 我们将再次使用
benchmark
函数将这些策略与left_join
进行比较:
ann2012full_dt <- data.table(ann2012full, key='industry_code')
industry_dt <- data.table(industry, key='industry_code')
op <- benchmark(
DT = data.table::merge(ann2012full_dt, industry_dt,
by='industry_code', all.x=T),
PLYR = plyr::join(ann2012full, industry,
by='industry_code',type='left'),
DPLYR = dplyr::left_join(ann2012full, industry),
DPLYR2 = dplyr::left_join(ann2012full_dt, industry_dt),
MERGE = merge(ann2012full, industry,
by='industry_code', all.x=T),
order='relative',
replications=5
)
您可以参考以下屏幕截图,获取上述命令的输出:
在这里,我们看到data.table
方法比任何其他策略都快得多。 对于特定任务,使用dplyr
的速度要慢 12 倍,plyr
的速度要慢 100 倍,而标准的merge
方法要慢 200 倍。 将data.frame
对象转换为data.table
对象会有一些开销,但是此任务的优势已克服了这一开销。
R 中时间基准测试的基本功能是system.time
函数。 此函数记录表达式求值开始的时间,运行表达式,然后记下表达式完成的时间。 然后,它报告两次的差异。 默认情况下,垃圾回收会在每次评估之前进行,以便结果更加一致,并为每次评估释放最大的内存。
rbenchmark
软件包中的benchmark
功能提供了更大的灵活性。 它包装了system.time
函数,并允许在一次运行中评估多个表达式。 它还可以进行一些基本计算(例如相对时间)来简化报告。
根据此处的任务,fread
使用强大的优化 C 函数读取数据,从而实现了高度的速度优化。 read.csv
函数仅逐行读取数据文件,并使用逗号分隔符解析字段。 通过使用colClasses
选项在read.csv
中指定列类型,我们可以在实验中提高速度,因为确定数据类型会消耗一些执行时间。 load
函数从使用save
函数创建的 RData
文件中读取数据,该文件存储 R 对象的二进制表示形式。 它压缩了很多数据,但是我们发现,读取数据比加载 RData
文件更有效。
我们设定为基准的第二项任务是将就业数据ann2014full
与industry
行业代码的数据对象一起左外连接。 前者有 3,556,289 行和 15 列,而后者有 2,469 行和两列。 它们基于公共变量industry_code
合并。 在左联接中,将保留ann2014full
的所有行。 为此,merge
命令将使用all.x=T
选项。 join
功能具有用于左连接的type='left'
选项。 对于 data.table
合并,我们首先将data.frame
对象转换为data.table
对象,并指定每个对象具有相同的键变量(请考虑数据库中的索引)industry_code
。 然后,使用此键变量合并 data.table
对象。
此代码段中有一些新的代码格式。 我们使用plyr::join
和dplyr::left_join
,而不仅仅是join
和left_join
。 这种编码方式明确指定我们正在使用来自特定程序包的特定功能,以避免混淆。 有时,当您在两个都装入 R 的两个不同包中具有相同名称的函数时,这种编码风格很有用。
data.table
软件包提供了非常快速的工具来进行数据加载,修改和联接。 data.table
对象是data.frame
包的派生对象,R 中输入data.frame
对象的许多函数也可以导入data.table
对象。 因此,data.table
对象成为矩形数据的默认容器。
- Hadley Wickham 在他的在线书籍中有一个关于基准测试的很好的阐述,可以在这个页面上找到。 他推广
microbenchmark
软件包以进行基准测试。