在本章中,我们将介绍以下内容:
- 获取汽车燃油效率数据
- 为您的第一个项目准备 R
- 将汽车燃油效率数据导入 R
- 探索和描述燃油效率数据
- 分析一段时间内的汽车燃油效率
- 调查汽车的品牌和型号
我们将在本书中介绍的第一个项目是对汽车燃油经济性数据的分析。 我们将用于分析此数据集的主要工具是 R 统计编程语言。 R 通常被称为数据科学的通用语言,因为它是目前最流行的统计和数据分析语言。 从本书示例中可以看到,R 是用于数据处理,分析,建模,可视化以及创建有用的脚本来完成分析任务的出色工具。
本章中的食谱将大致遵循数据科学流程中的以下五个步骤:
- 获得
- 探索与理解
- 蒙混,争吵和操纵
- 分析与建模
- 沟通与运营
在流程方面,数据科学的支柱是数据科学流水线,为了精通数据科学,您需要获得在执行此过程中的经验,同时交换各种工具和方法,以便您始终使用这些工具和方法。 适用于您正在分析的数据集。
本章的目的是通过逐步的示例指导您完成有关汽车燃油效率的分析项目,您可以从中学习并逐步应用于将来的其他数据集和分析项目。 将本章视为对以后更长且更具挑战性的章节的热身。
每个数据科学项目都始于数据,本章以相同的方式开始。 对于本配方,我们将深入研究一个数据集,其中包含燃油效率指标,这些指标随时间推移以英里每加仑(MPG)衡量,适用于 自 1984 年以来一直是美国。此数据由美国能源部和美国环境保护署提供。 除了燃油效率数据外,该数据集还包含列出的汽车的若干特征和属性,从而提供了汇总和分组数据的机会,以确定历史上哪个组往往具有更高的燃油效率以及多年来如何改变。 可以在这个页面获得最新版本的数据集,有关数据集中变量的信息可以在这个页面找到。 数据的最新更新时间为 2013 年 12 月 4 日,下载日期为 2013 年 12 月 8 日。
我们建议您使用本书代码随附的数据集副本,以确保本章中描述的结果与您的努力相匹配。
要完成此食谱,您将需要一台可访问 Internet 的计算机和您选择的文本编辑器。
执行以下简单步骤来获取本章其余部分所需的数据:
- 从以下位置下载数据集。
- 用您选择的解压缩工具解压缩
vehicles.csv
并将其移到您的工作代码目录中。 - 请花一点时间,然后使用 Microsoft Excel,Google Spreadsheet 或简单的文本编辑器打开未压缩的
vehicles.csv
文件。 逗号分隔值(CSV)文件使用起来非常方便,因为可以使用非常基本且免费的工具对其进行编辑和查看。 打开文件后,滚动浏览某些数据,并了解要使用的内容。 - 导航至这个页面。
- 选择并复制数据描述下车辆标题下方的所有文本,并将其粘贴到文本文件中。 不包括排放方向。 将此文件另存为
varlabels.txt
在您的工作目录中。 文件的前五行如下:
atvtype - type of alternative fuel or advanced technology vehicle
barrels08 - annual petroleum consumption in barrels for fuelType1 (1)
barrelsA08 - annual petroleum consumption in barrels for fuelType2 (1)
charge120 - time to charge an electric vehicle in hours at 120 V
charge240 - time to charge an electric vehicle in hours at 240 V
请注意,为方便起见,在包含本章代码的存储库中提供了此文件。
在第一个简单的食谱中没有太多要解释的内容,但是请注意,我们在这里相对容易地开始。 在许多数据科学项目中,您将无法如此轻松地访问和查看数据。
对于以下食谱,您将需要在计算机上安装 R 统计编程语言(基本 R 或 RStudio,但作者强烈建议使用功能强大且免费的 RStudio)和汽车燃油效率数据集。 此快速食谱将帮助您确保完成此分析项目所需的一切。
您将需要互联网连接才能完成此食谱,并且根据上一章的说明,我们假定您已为特定平台安装了 RStudio。
如果您使用的是 RStudio,则以下三个步骤将使您准备就绪:
- 在计算机上启动 RStudio。
- 在 R 控制台提示下,安装此项目所需的三个 R 软件包:
install.packages("plyr")
install.packages("ggplot2")
install.packages("reshape2")
- 加载 R 软件包,如下所示:
library(plyr)
library(ggplot2)
library(reshape2)
R 的实力来自围绕该语言开发的社区以及由社区中的人创建和提供的软件包。 当前,您可以导入和利用 4,000 多个软件包和库,以使您的数据分析任务更加轻松。
Hadley Wickham 博士是 R 社区的著名成员,他制作了许多备受推崇且经常使用的 R 软件包。 在本章中,您将主要使用他最大的两个作品plyr
和ggplot2
,以及第三个名为reshape2
的软件包。 软件包plyr
将用于将本章稍后说明的拆分-合并-组合数据分析模式应用于我们的数据集,ggplot2
将使复杂的数据可视化变得更加容易。
一旦下载并安装了先前食谱中的所有内容,并为第一个项目准备 R,就可以将数据集导入 R 以开始进行一些初步分析并了解数据的外观。
本章中的许多分析都是累积性的,以前的配方将用于后续的配方。 因此,如果您完成了上一个食谱,则应具备继续进行所需的一切。
以下步骤将引导您完成将数据初始导入 R 环境的过程:
- 首先,将工作目录设置为我们保存
vehicles.csv.zip
文件的位置:
setwd("path")
替换实际目录的路径。
- 只要您知道要加载的 ZIP 档案中文件的文件名,我们就可以直接从压缩(ZIP)文件中加载数据:
vehicles <- read.csv(unz("vehicles.csv.zip", "vehicles.csv"),
stringsAsFactors = F)
- 要查看是否有效,让我们使用
head
命令显示数据的前几行:
head(vehicles)
您应该看到屏幕上打印的数据集的前几行。
请注意,我们可以使用 tail 命令,该命令将显示数据帧的最后几行,而不是前几行。
labels
命令为vehicles.csv
文件提供了变量标签。 请注意,由于labels
是 R 中的一个函数,因此我们使用labels
。快速浏览该文件将显示变量名称及其解释由-
分隔。 因此,我们将尝试使用-
作为分隔符来读取文件:
labels <- read.table("varlabels.txt", sep = "-", header = FALSE) ## Error: line 11 did not have 2 elements
- 这行不通! 仔细查看该错误,可以发现在数据文件的第 11 行中有两个
-
符号,因此与其他行不同,它分成三个部分而不是两个部分。 我们需要更改文件读取方法以忽略带连字符的单词:
labels <- do.call(rbind, strsplit(readLines("varlabels.txt"), " - "))
- 为了检查它是否有效,我们再次使用 head 函数:
head(labels)
[,1] [,2]
[1,] "atvtype" "type of alternative fuel or advanced
technology vehicle"
[2,] "barrels08" "annual petroleum consumption in barrels for
fuelType1 (1)"
[3,] "barrelsA08" "annual petroleum consumption in barrels for
fuelType2 (1)"
[4,] "charge120" "time to charge an electric vehicle in hours
at 120 V"
[5,] "charge240" "time to charge an electric vehicle in hours
at 240 V"
让我们逐一分解步骤 5 中的最后一个复杂语句,从最内部开始并向外进行。 首先,让我们逐行阅读文件:
x <- readLines("varlabels.txt")
每行需要在字符串-
处分割。 空格很重要,因此我们不分割带连字符的单词(例如第 11 行中的字符)。 这导致每一行作为字符串向量分成两部分,并且向量存储在单个列表中:
y <- strsplit(x, " - ")
现在,我们将这些向量堆叠在一起以形成字符串矩阵,其中第一列是变量名称,第二列是变量的描述:
labels <- do.call(rbind, y)
精明的读者可能已经注意到read.csv
函数调用包括 stringsAsFactors = F
作为其最终参数。 默认情况下,R 将字符串转换为数据类型,在许多情况下称为因素。 因素是 R 的分类数据类型的名称,可以将其视为应用于数据的标签或标记。 在内部,R 将因子存储为整数,并映射到适当的标签。 此技术允许较早版本的 R 将因子存储在比相应字符少得多的内存中。
分类变量没有顺序感(其中一个值被认为大于另一个值)。 在以下代码段中,我们创建一个快速玩具示例,将character
类的四个值转换为 factor 并进行比较:
colors <- c('green', 'red', 'yellow', 'blue')
colors_factors <- factor(colors)
colors_factors
[1] green red yellow blue
Levels: blue green red yellow
colors_factors[1] > colors_factors[2]
[1] NA
Warning message:
In Ops.factor(colors_factors[1], colors_factors[2]) :
>not meaningful for factors
但是,存在一个有序的分类变量,在统计世界中也称为序数数据。 有序数据就像分类数据一样,只有一个例外。 数据具有规模感或价值感。 可以说一个值大于另一个值,但是无法测量差异的大小。
此外,在将数据导入 R 时,我们经常会遇到这样的情况:一列数字数据可能包含非数字条目。 在这种情况下,R 可能会将数据列作为因素导入,这通常不是数据科学家想要的。 从因子到字符的转换是相对常规的,但是从因子到数字的转换可能有点棘手。
R 能够导入多种格式的数据。 在此配方中,我们处理了 CSV 文件,但也可以使用 Microsoft Excel 文件。 首选 CSV 文件,因为它们在整个操作系统中都得到普遍支持,并且具有更高的可移植性。 此外,R 可以从众多流行的统计程序(包括 SPSS,Stata 和 SAS)中导入数据。
现在我们已经将汽车燃油效率数据导入 R 并了解了一些有关导入的细微差别,下一步是对数据集进行一些初步分析。 该分析的目的是探索数据的外观,并使用 R 的一些最基本的命令来弄清数据。
如果您已完成上一个食谱,则应具备继续进行所需的一切。
以下步骤将引导您完成对数据集的初步探索,并在其中计算一些基本参数:
- 首先,让我们找出数据中有多少个观测值(行):
nrow(vehicles)
## 34287
- 接下来,让我们找出数据中有多少个变量(列):
ncol(vehicles)
## 74
- 现在,让我们使用
names
函数来了解数据帧中存在哪些数据列:
> names(vehicles)
前面的命令将为您提供以下输出:
幸运的是,这些列或变量名中的许多都具有很好的描述性,使我们对它们可能包含的内容有所了解。 请记住,可以在这个页面上找到有关变量的更详细说明。
- 通过计算
year
列中唯一值的向量,然后计算该向量的长度,让我们找出此数据集中包含多少唯一数据年:
length(unique(vehicles[, "year"]))
## 31
- 现在,我们使用
min
和max
函数确定数据集中的前几年和后几年:
first_year <- min(vehicles[, "year"])
## 1984
last_year <- max(vehicles[, "year"])
## 2014
请注意,我们可以使用 tail 命令,该命令将显示数据帧的最后几行,而不是前几行。
- 另外,由于我们可能会大量使用
year
变量,因此,请确保我们涵盖了每年。 从 1984 年到 2014 年的年份列表应包含 31 个唯一值。 要对此进行测试,请使用以下命令:
> length(unique(vehicles$year))
[1] 31
- 接下来,让我们找出哪种类型的燃料用作汽车的主要燃料类型:
table(vehicles$fuelType1)
## Diesel Electricity Midgrade Gasoline Natural Gas
## 1025 56 41 57
## Premium Gasoline Regular Gasoline
## 8521 24587
由此可见,数据集中的大多数汽车都使用普通汽油,第二常见的燃料类型是特级汽油。
- 让我们探索这些汽车使用的变速器类型。 我们首先需要通过将其设置为
NA
来处理所有丢失的数据:
vehicles$trany[vehicles$trany == ""] <- NA
- 现在
trany
列为text
,我们只关心汽车的变速箱是自动还是手动。 因此,我们使用substr
函数提取每个trany
列值的前四个字符,并确定其是否等于Auto
。 如果是这样,我们将设置一个新变量trany2
,该变量等于Auto;
,否则,该值将设置为Manual
:
vehicles$trany2 <- ifelse(substr(vehicles$trany, 1, 4) == "Auto",
"Auto", "Manual")
- 最后,我们将新变量转换为因子,然后使用表格函数查看值的分布:
vehicles$trany <- as.factor(vehicles$trany)
table(vehicles$trany2)
## Auto Manual
## 22451 11825
我们可以看到,具有自动变速箱的汽车模型的数量大约是具有手动变速箱的汽车模型的两倍。
数据框是 R 使用的强大数据类型,我们将在整个食谱中充分利用它。 数据框使我们能够将不同数据类型(数字,字符串,逻辑,因子等)的变量分组为相关信息行。 一个示例将是客户信息的数据框。 数据框中的每一行都可以包含人员名称(字符串),以及年龄(数字),性别(因素)和标记,以指示他们是否是当前客户(布尔值)。 如果您熟悉关系数据库,则这很像数据库中的表。
此外,在本食谱中,我们研究了几种快速读取导入到 R 中的数据集的方法。最值得注意的是,我们使用了功能强大的table
函数来为fuelType1
变量的出现次数进行计数。 此功能具有更多功能,包括交叉列表,如下所示:
with(vehicles, table(sCharger, year))
前面的命令将为您提供以下输出:
在这里,我们查看了有无超级充电器的年份(按年)的汽车型号(而且我们发现,超级充电器似乎比过去更受大众欢迎)。
另外,请注意,我们使用with
命令。 该命令告诉 R 在执行后续命令(在本例中为 table)时,将车辆用作默认数据。 因此,我们可以省略sCharger
和year
列名称的开头,并在其前面加上数据框和车辆的名称,后跟美元符号。
为了提供有关数据导入的警告提示,让我们更仔细地查看sCharger
和tCharger
列。 请注意,这些列分别指示汽车是否包含超级充电器或涡轮增压器。
从sCharger
开始,我们看一下变量的类和数据框中存在的唯一值:
> class(vehicles$sCharger)
[1] "character"
> unique(vehicles$sCharger)
[1] "" "S"
接下来,我们看tCharger
,期望情况是一样的:
> class(vehicles$tCharger)
[1] "logical"
> unique(vehicles$tCharger)
[1] NA TRUE
但是,我们发现这两个看似相似的变量完全是不同的数据类型。 尽管tCharger
变量是逻辑变量,在其他语言中也称为布尔变量,并且它用于表示TRUE
和FALSE
的二进制值,但sCharger
变量似乎更通用 字符数据类型。 似乎有问题。 在这种情况下,由于可以,让我们检查原始数据。 幸运的是,数据位于.csv
文件中,我们可以使用简单的文本编辑器来打开和读取文件(建议将 Windows 上的记事本和 Unix 系统上的 vi 用作该任务,但是请随意使用您喜欢的基本功能 文本编辑器)。 当我们打开文件时,我们可以看到sCharger
和tCharger
数据列为空白,或分别包含**
S**
或**
T**
。
因此,与字符T
相对,R 已读入tCharger
列中的 T
字符作为布尔TRUE
变量。 这不是致命的缺陷,可能不会影响分析。 但是,诸如此类的未检测到的 bug 可能会导致分析流程之外的问题,并且需要进行大量重复工作。
现在,我们已经成功导入了数据,并查看了一些重要的高级统计数据,这些统计数据使我们对数据集中的值以及某些要素出现的频率有了基本的了解。 通过此食谱,我们将通过研究一些随时间推移以及与其他数据点有关的燃油效率指标来继续探索。
如果您完成了上一个食谱,则应具备继续进行所需的一切。
以下步骤将同时使用plyr
和图形库ggplot2
来浏览数据集:
- 让我们从平均水平来看,是否存在 MPG 随时间变化的总体趋势。 为此,我们使用
plyr
包中的ddply
函数获取vehicles
数据帧,按年份汇总行,然后针对每个组计算平均公路,城市并结合燃油效率 。 然后将结果分配给新数据帧mpgByYr
。 请注意,这是我们的 split-apply-combine 的第一个示例。 我们按年份将数据框架分为几组,将均值函数应用于特定变量,然后将结果合并为一个新的数据框架:
mpgByYr <- ddply(vehicles, ~year, summarise, avgMPG =
mean(comb08), avgHghy = mean(highway08), avgCity =
mean(city08))
- 为了更好地理解此新数据帧,我们将其传递给
ggplot
函数,告诉它使用点将avgMPG
变量与year
变量相对应地绘制。 另外,我们指定我们希望轴标签,标题,甚至是平滑的条件mean (geom_smooth())
都以图的阴影区域表示:
ggplot(mpgByYr, aes(year, avgMPG)) + geom_point() +
geom_smooth() + xlab("Year") + ylab("Average MPG") +
ggtitle("All cars")
## geom_smooth: method="auto" and size of largest group is <1000, so using
## loess. Use 'method = x' to change the smoothing method.
前面的命令将为您提供以下图表:
- 基于这种可视化,可能会得出结论,在过去几年中,所售汽车的燃油经济性有了极大的提高。 但是,这可能会引起误解,因为在随后的几年中出现了更多的混合动力和非汽油动力汽车,如下所示:
table(vehicles$fuelType1)
## Diesel Electricity Midgrade Gasoline Natural Gas
## 1025 56 41 57
## Premium Gasoline Regular Gasoline
## 8521 24587
- 让我们看一下汽油车,尽管非汽油动力车不多,然后重画前面的图。 为此,我们使用子集函数创建一个新的数据帧
gasCars
,该数据帧仅包含其中fuelType1
变量是值子集中之一的车辆行:
gasCars <- subset(vehicles, fuelType1 %in% c("Regular Gasoline",
"Premium Gasoline", "Midgrade Gasoline") & fuelType2 == "" & atvType != "Hybrid")
mpgByYr_Gas <- ddply(gasCars, ~year, summarise, avgMPG = mean(comb08))
ggplot(mpgByYr_Gas, aes(year, avgMPG)) + geom_point() +
geom_smooth() + xlab("Year") + ylab("Average MPG") + ggtitle("Gasoline cars")
## geom_smooth: method="auto" and size of largest group is <1000, so using
## loess. Use 'method = x' to change the smoothing method.
前面的命令将为您提供以下图表:
- 最近生产的大型发动机汽车数量减少了吗? 如果是这样,这可以解释增加的原因。 首先,让我们验证具有较大发动机的汽车的燃油效率是否较差。 我们注意到
displ
变量代表发动机的排量(以升为单位),目前是一个字符串变量,我们需要将其转换为数字变量:
typeof(gasCars$displ)
## "character"
gasCars$displ <- as.numeric(gasCars$displ)
ggplot(gasCars, aes(displ, comb08)) + geom_point() +
geom_smooth()
## geom_smooth: method="auto" and size of largest group is >=1000, so using
## gam with formula: y ~ s(x, bs = "cs"). Use 'method = x' to change the
## smoothing method.
## Warning: Removed 2 rows containing missing values
(stat_smooth).
## Warning: Removed 2 rows containing missing values
(geom_point).
前面的命令将为您提供以下图表:
数据的散点图提供了令人信服的证据,表明发动机排量和燃油效率之间存在负相关,甚至呈负相关。 因此,较小的汽车往往更省油。
- 现在,让我们看看在以后的几年中是否还会生产更多的小型车,这可以解释燃油效率的急剧提高:
avgCarSize <- ddply(gasCars, ~year, summarise, avgDispl = mean(displ))
ggplot(avgCarSize, aes(year, avgDispl)) + geom_point() +
geom_smooth() + xlab("Year") + ylab("Average engine displacement (l)")
## geom_smooth: method="auto" and size of largest group is <1000, so using
## loess. Use 'method = x' to change the smoothing method.
## Warning: Removed 1 rows containing missing values (stat_smooth).
## Warning: Removed 1 rows containing missing values (geom_point).
前面的命令将为您提供以下图表:
- 从上图可以看出,自 2008 年以来,平均发动机排量已经大幅下降。为了更好地了解这可能对燃油效率的影响,我们可以将 MPG 和排量按年放在同一张图表上。 使用
ddply
,我们创建一个新的数据框byYear
,其中包含按年计的平均燃油效率和平均发动机排量:
byYear <- ddply(gasCars, ~year, summarise, avgMPG = mean(comb08),
avgDispl = mean(displ))
> head(byYear)
year avgMPG avgDispl
1 1984 19.12162 3.068449
2 1985 19.39469 NA
3 1986 19.32046 3.126514
4 1987 19.16457 3.096474
5 1988 19.36761 3.113558
6 1989 19.14196 3.133393
head
函数向我们显示结果数据帧具有三列:year
,avgMPG
和avgDispl
。 要使用ggplot2
的分面功能在单独但对齐的图上按年份显示Average MPG
和Avg engine displacement
,我们必须融化数据框,将其从所谓的宽格式转换为长格式:
byYear2 = melt(byYear, id = "year")
levels(byYear2$variable) <- c("Average MPG", "Avg engine displacement")
head(byYear2)
year variable value
1 1984 Average MPG 19.12162
2 1985 Average MPG 19.39469
3 1986 Average MPG 19.32046
4 1987 Average MPG 19.16457
5 1988 Average MPG 19.36761
6 1989 Average MPG 19.14196
- 如果使用
nrow
功能,我们可以看到byYear2
数据帧有 62 行,byYear
数据帧只有 31 行。byYear
中的两个单独列(avgMPG
和avgDispl
) 现在已被byYear2
数据框中的一个新列(value
)融化。 请注意,byYear2
数据框中的变量列用于标识该值表示的列:
ggplot(byYear2, aes(year, value)) + geom_point() +
geom_smooth() + facet_wrap(~variable, ncol = 1, scales =
"free_y") + xlab("Year") + ylab("")
## geom_smooth: method="auto" and size of largest group is <1000, so using
## loess. Use 'method = x' to change the smoothing method.
## geom_smooth: method="auto" and size of largest group is <1000, so using
## loess. Use 'method = x' to change the smoothing method.
## Warning: Removed 1 rows containing missing values (stat_smooth).
## Warning: Removed 1 rows containing missing values (geom_point).
前面的命令将为您提供以下图表:
从该图可以看到以下内容:
- 发动机尺寸总体上一直增加到 2008 年,而大型汽车在 2006 年到 2008 年之间突然增加。
- 自 2009 年以来,平均汽车尺寸有所减少,这在一定程度上解释了燃油效率的提高。
- 直到 2005 年,平均汽车尺寸有所增加,但燃油效率大致保持不变。 这似乎表明多年来,发动机效率有所提高。
- 2006-2008 年很有趣。 尽管平均发动机尺寸突然增加,但 MPG 仍与前几年大致相同。 这种表面上的差异可能需要更多的调查。
- 考虑到排量较小的发动机的发展趋势,让我们看看自动变速箱或手动变速箱对四缸发动机的效率是否更高,以及效率随时间的变化情况:
gasCars4 <- subset(gasCars, cylinders == "4")
ggplot(gasCars4, aes(factor(year), comb08)) + geom_boxplot() + facet_wrap(~trany2, ncol = 1) + theme(axis.text.x = element_text(angle = 45)) + labs(x = "Year", y = "MPG")
前面的命令将为您提供以下图表:
- 这次,
ggplot2
用于创建箱形图,以帮助可视化每年的值分布(而不仅仅是单个值,例如平均值)。 - 接下来,让我们看一下每年可用手动车比例的变化:
ggplot(gasCars4, aes(factor(year), fill = factor(trany2))) +
geom_bar(position = "fill") + labs(x = "Year", y = "Proportion
of cars", fill = "Transmission") + theme(axis.text.x =
element_text(angle = 45)) + geom_hline(yintercept = 0.5,
linetype = 2)
前面的命令将为您提供以下图表:
ggplot2
库是 Wilkinson,Anand 和 Grossman for R 的图形基础语法的开源实现。图形语法试图将统计数据可视化分解为组成部分,以更好地理解这种方式 图形已创建。 使用ggplot2
,Hadley Wickham 采纳了这些想法并实现了分层的方法,从而使用户可以快速地从单个零件中组装复杂的可视化效果。 例如,以该配方的第一张图表为例,该图表显示了特定年份中所有型号的汽车在一段时间内的平均燃油效率:
ggplot(mpgByYr, aes(year, avgMPG)) + geom_point() + geom_smooth() +
xlab("Year") + ylab("Average MPG") + ggtitle("All cars")
要构建此图,我们首先告诉ggplot
将用作该图数据的数据框(mpgByYr
),然后通过美学映射图告诉ggplot2
哪些变量将映射到该图的视觉特征中 阴谋。 在这种情况下,aes(year, avgMPG)
隐式指定年份将映射到x
轴,而avgMPG
将映射到 y 轴。 geom_point()
告诉库将指定数据绘制为点,然后第二个geom
geom_smooth()
添加阴影区域,以显示相同数据的平滑均值(默认情况下,置信区间设置为0.95
)。 。 最后,xlab()
,ylab()
和ggtitle()
函数用于在图上添加标签。 因此,我们可以在一行代码中生成一个复杂的发布质量图; ggplot2
能够绘制更复杂的图。
另外,必须注意ggplot2
和一般的图形语法不会告诉您如何最好地可视化数据,但可以为您提供快速执行此操作的工具。 如果您需要有关此主题的更多建议,我们强烈建议您研究 Edward Tufte 的著作,他有很多有关此事的书籍,包括经典的定量信息的可视化显示,美国印刷出版社。 此外,ggplot2
不允许动态数据可视化。
在步骤 9 中,似乎手动变速箱比自动变速箱更有效,并且从 2008 年开始,它们平均呈现出相同的增长。但是,这里有些奇怪。 在后来的几年中,似乎有很多非常高效的汽车(不到 40 MPG)具有自动变速箱,并且几乎没有在相同的时间范围内具有类似效率的手动变速箱汽车。 在早些年,这种模式是相反的。 每年手动汽车的比例有变化吗? 是的。
通过本食谱,我们将使用两个非常重要的 R 包plyr
和ggplot2
将您带入 R 进行数据分析的深层次。 就像传统的软件开发具有用于通用构造的设计模式一样,在数据科学领域中也出现了一些这样的模式。 最引人注目的之一是 Hadley Wickham 博士突出显示的拆分组合模式。 在这种策略中,可以通过一些变量将问题分解为更小,更易于管理的部分。 汇总后,您可以对新的分组数据执行操作,然后将结果合并到新的数据结构中。 如您在本食谱中所见,我们反复使用了“拆分-应用-合并”的策略,因此从许多不同的角度检查了数据。
除了plyr
之外,此配方还大量利用了ggplot2
库,值得进一步介绍。 我们将避免提供广泛的ggplot2
教程,因为在线上有许多优秀的教程。 重要的是您了解ggplot2
如何使您以简洁的方式构建如此复杂的统计可视化的重要思想。
- 《数据分析的拆分应用组合策略》
- 《图形语法》,Leland Wilkinson,Springer Science & 商业媒体
ggplot2
软件包文章- 《图形分层语法》文章
关于该数据集的第一组问题提出并回答后,让我们继续进行其他分析。
如果您完成了上一个食谱,则应具备继续进行所需的一切。
本食谱将调查汽车的品牌和型号以及它们随着时间的变化:
- 让我们看一下汽车的品牌和型号如何随时间改变燃油效率。 首先,让我们看看这段时间在美国销售的汽车的制造商和型号的频率,并重点介绍四缸汽车:
carsMake <- ddply(gasCars4, ~year, summarise, numberOfMakes = length(unique(make)))
ggplot(carsMake, aes(year, numberOfMakes)) + geom_point() + labs(x = "Year", y = "Number of available makes") + ggtitle("Four cylinder cars")
从下图中我们可以看到,在这段时期内,可供销售的商品数量有所下降,尽管最近一段时间有所增加。
- 我们能否看一下这项研究每年可用的品牌? 我们发现在此期间,每年只有 12 家制造商生产四缸汽车:
uniqMakes <- dlply(gasCars4, ~year, function(x)
unique(x$make))
commonMakes <- Reduce(intersect, uniqMakes)
commonMakes
## [1] "Ford" "Honda" "Toyota" "Volkswagen"
"Chevrolet"
## [6] "Chrysler" "Nissan" "Dodge" "Mazda"
"Mitsubishi"
## [11] "Subaru" "Jeep"
- 这些制造商随着时间的推移在燃油效率方面做得如何? 我们发现大多数制造商在这段时间内都表现出了进步,尽管在过去五年中有几家制造商证明了燃油效率的显着提高:
carsCommonMakes4 <- subset(gasCars4, make %in% commonMakes)
avgMPG_commonMakes <- ddply(carsCommonMakes4, ~year + make,
summarise, avgMPG = mean(comb08))
ggplot(avgMPG_commonMakes, aes(year, avgMPG)) + geom_line() +
facet_wrap(~make, nrow = 3)
前面的命令将为您提供以下图表:
在步骤 2 中,肯定有一些有趣的魔术在起作用,仅用几行代码就可以完成很多工作。 这既是 R 的美观方面也是有问题的方面。它之所以优美,是因为它允许简洁地表达程序上复杂的思想,但是这是有问题的,因为如果您不熟悉特定的库,R 代码可能会非常难以理解。
在第一行中,我们使用dlply
(不是ddply
)来获取gasCars4
数据帧,按年份分割它,然后将唯一函数应用于make
变量。 对于每年,计算唯一可用的汽车制造商列表,然后dlply
返回这些列表的列表(每年一个元素)。 注意dlply
而非ddply
,因为它以数据帧(d
)作为输入并返回列表(l
)作为输出,而ddply
则以数据帧(d
)作为输入 输入和输出数据帧(d
):
uniqMakes <- dlply(gasCars4, ~year, function(x) unique(x$make))
commonMakes <- Reduce(intersect, uniqMakes)
commonMakes
下一行更加有趣。 它使用Reduce
高阶函数,这与 Google 引入的作为 Hadoop 基础的 map reduce 编程范例中的Reduce
函数和思想相同。 在某些方面,R 是一种功能编程语言,并提供一些更高阶的功能作为其核心的一部分。 高阶函数接受另一个函数作为输入。 在这一行中,我们将intersect
函数传递给Reduce
,该函数将intersect
函数成对应用到以前创建的每年唯一品牌列表中的每个元素。 最终,这导致每年都会有一份汽车制造清单。
这两行代码表达了一个非常简单的概念(确定每年所有的汽车制造商),用两个段落来描述。
此配方中的最终图形是ggplot2
的多面图形功能的一个很好的示例。 添加+facet_wrap(~make, nrow = 3)
会告诉ggplot2
,我们希望为每种汽车品牌使用一组独立的轴,并将这些子图分布在三个不同的行之间。 这是一种非常强大的数据可视化技术,因为它使我们能够清楚地看到可能仅针对某个变量的特定值而显现的模式。
在第一个数据科学项目中,我们保持了简单。 数据集本身很小-在基本的笔记本电脑上,未压缩,易于存储和处理的只有 12 MB。 我们使用 R 导入数据集,检查某些(但不是全部)数据字段的完整性,并汇总数据。 然后,我们通过询问许多问题并使用两个关键库plyr
和ggplot2
来操作数据并可视化结果,以探索数据。 在这个数据科学流水线中,我们的最后阶段只是编写用来总结我们的结论和ggplot2
产生的可视化效果的文字。