ggplot2学习笔记7:通过图层逐层构建图形
Build a Plot Layer by Layer
5.1 介绍(Introduction)
ggplot2背后的一个关键思想是,它允许轻松地迭代,一次一层地构建一个复杂的绘图。每个图层可以来自不同的数据集,并且具有不同的美学映射,从而可以创建复杂的绘图,显示来自多个源的数据。
在本章中,将深入了解层的细节,以及如何控制所有五个组件:数据Data
、美学映射Aesthetic Mappings
、几何对象Geom
、统计变换Stat
和位置调整Position Adjustments
。
5.2 创建一张图形(Building a Plot)
我们要明确,在绘图过程实际上是有两个步骤。以mpg数据集为例,第一步,我们使用默认数据集和美学映射创建一个图:
p <- ggplot(mpg, aes(displ, hwy))
p
此时我们已经创建好了一幅图,表面上是一块画板,实际上这幅图中包含了mpg数据集中的所有数据和坐标轴信息,唯一缺的就是数据的可视化形式。
下面是第二步,通过几何对象添加图层:
p + geom_point()
几何对象point
,通过函数geom_point()
添加,()
中没有任何参数,代表使用默认值。使用函数geom_point()
是捷径,实际上,在后台它调用该layer()
函数以创建一个新层:
p + layer(mapping = NULL, data = NULL,geom = "point", stat = "identity",position = "identity"
)
layer()
函数调用完全指定了该层的五个组成部分:
- mapping:映射,就是
aes()
函数,通常省略,NULL
就是指默认的ggplot()
函数中的映射 - data:数据,覆盖默认数据集,通常省略,
NULL
就是默认取ggplot()
中的数据集 - geom:几何对象,包含很多美学参数,例如颜色等,在这里设置不会成为标度。
- stat:统计变换,执行一些统计汇总,默认设置为
"identity"
时保持不变。这个参数在直方图和平滑曲线图中应用较多。geom
和stat
设置一个即可,每个geom
都有一个默认stat
,每个stat
默认一个geom
。 - position:位置,调整遮盖、堆叠的情况
5.3 数据(Data)
ggplot2
的作用只是将数据框可视化。在使用之前应该提前整理你的数据框,使其整齐、易于操作.
You’ll learn about tidy data in Chap. 9, but for now, all you need to know is that a tidy data frame has variables in the columns and observations in the rows.(列变量行观测)
library(ggplot2)
library(dplyr) #包含data_frame()函数
mpg #在包ggplot2中mod <- loess(hwy ~ displ, data = mpg) #loess()生成线性模型
grid <- data_frame(displ = seq(min(mpg$displ), max(mpg$displ), length = 50))
grid$hwy <- predict(mod, newdata = grid)
grid
#> Source: local data frame [50 x 2]
#>
#> displ hwy
#> (dbl) (dbl)
#> 1 1.60 33.1
#> 2 1.71 32.2
#> 3 1.82 31.3
#> 4 1.93 30.4
#> 5 2.04 29.6
#> 6 2.15 28.8
#> # … with 44 more rows
接下来,我将分离与预测值特别远的观测:
std_resid <- resid(mod) / mod$s #标准残差
outlier <- filter(mpg, abs(std_resid) > 2)
outlier #称之为异常值
#> # A tibble: 6 x 11
#> manufacturer model displ year cyl trans drv cty hwy fl class
#> <chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr> <chr>
#> 1 chevrolet corvet… 5.7 1999 8 manual… r 16 26 p 2seater
#> 2 pontiac grand … 3.8 2008 6 auto(l… f 18 28 r midsize
#> 3 pontiac grand … 5.3 2008 8 auto(s… f 16 25 p midsize
#> 4 volkswagen jetta 1.9 1999 4 manual… f 33 44 d compact
#> 5 volkswagen new be… 1.9 1999 4 manual… f 35 44 d subcom…
#> 6 volkswagen new be… 1.9 1999 4 auto(l… f 29 41 d subcom…
有了这些新的数据集,我可以通过覆盖一条平滑线并标记外围点来改善我们的初始散点图:
ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_line(data = grid, colour = "blue", size = 1.5) + geom_text(data = outlier, aes(label = model))
在此示例中,每个图层使用不同的数据集。我们可以用另一种方式定义相同的图,省略默认数据集,并为每个图层指定一个数据集:
ggplot(mapping = aes(displ, hwy)) + geom_point(data = mpg) + geom_line(data = grid) + geom_text(data = outlier, aes(label = model))
5.4 美学映射(Aesthetic Mappings)
映射函数为aes()
,函数aes()
采用如下所示的美学变量的对应规则:
aes(x = displ, y = hwy, colour = class)
x =
和y =
也可以省略,即放在第一个逗号前的变量默认是x轴,第二个逗号前的变量默认在y轴。
aes()
中可以进行一些简单地运算,比如,aes(log(carat), log(price))
,如果转换复杂,最好将转换移出aes()
调用,移至显式dplyr::mutate()
调用。切勿在aes()
中使用美元符号$
(例如:diamonds$carat
)。
5.4.1 在图表或图层中添加图形属性
在上面散点图的基础上,用不同颜色代表不同class
,也就是将一个变量映射成一个图形属性:
ggplot(mpg, aes(displ, hwy, colour = class)) +geom_point()
ggplot(mpg, aes(displ, hwy)) +geom_point(aes(colour = class))
ggplot(mpg, aes(displ)) +geom_point(aes(y = hwy, colour = class))
ggplot(mpg) +geom_point(aes(displ, hwy, colour = class))
上面的脚本显示图层只有一层,四幅图本质上是一样的
在每个层中,您可以添加,覆盖或删除映射。例如,如果您有一个以mpg
数据aes(displ, hwy)
为起点的图,则下表说明了所有三种操作:
运作方式 | 图层美学 | 结果 |
---|---|---|
加 |
aes(colour = cyl)
|
aes(displ, hwy, colour = cyl)
|
覆写 |
aes(y = cty)
|
aes(displ, cty)
|
去掉 |
aes(y = NULL)
|
aes(displ)
|
但是当图层不只一层之后,参数放在哪里,要搞清楚,比如下面的例子:
映射aes(colour = class)
放在ggplot
函数中:
ggplot(mpg, aes(displ, hwy, colour = class)) +geom_point() +geom_smooth(method = "lm", se = FALSE) +theme(legend.position = "none")
映射aes(colour = class)
只放在geom_point
图层中:
ggplot(mpg, aes(displ, hwy)) +geom_point(aes(colour = class)) +geom_smooth(method = "lm", se = FALSE) +theme(legend.position = "none")
5.4.2 设定和映射(Setting vs. Mapping)
改变图形外观有两种方法:设定和映射
将美学映射到变量(例如aes(colour = cut)
)或将其设置为常数(例如colour = "red"
)。如果希望外观由变量控制,则将规范放在其中aes()
;如果要覆盖默认大小或颜色,请将值放在之外aes()
。
以下绘图使用相似的代码创建,但输出却大不相同。
第一幅设置了点的颜色,第二幅则将颜色darkblue
作为新变量映射为图形属性。由于此值是离散的,因此默认色标在色轮上使用均匀分布的颜色,并且由于只有一个值,因此该颜色是桃红色的。
ggplot(mpg, aes(cty, hwy)) + geom_point(colour = "darkblue") ggplot(mpg, aes(cty, hwy)) + geom_point(aes(colour = "darkblue"))
还有一种映射值的方法,可绘制出第一幅图的外观:
ggplot(mpg, aes(cty, hwy)) + geom_point(aes(colour = "darkblue")) + scale_colour_identity()
将美学映射到常量有时很有用。例如,如果要显示具有不同参数的多个层,则可以“命名”每个层:
5.5 几何对象(Geometric objects, or geoms)
几何对象,控制你所创建图层的类型。例如,使用point
将创建散点图(scatterplot),而使用line
将创建线图(line plot)。
5.5.1 基础几何对象函数:
geom_blank()
:空白,可以用来限制轴的范围geom_point()
:散点图geom_path()
:路径图geom_ribbon()
:色带图,连续的x值所对应的y值范围geom_segment()
:线段图(线段或箭头),由开始和结束位置指向geom_rect()
:二维矩形图geom_polygon()
:填充多边形geom_text()
:文本注释
5.5.2 一个变量
离散型变量
geom_bar()
:条形图
连续型变量
geom_histogram()
: 直方图geom_density()
: 光滑密度曲线图geom_dotplot()
: 点直方图geom_freqpoly()
: 频率多边形图
5.5.3 两个变量
都连续
geom_point()
: 散点图geom_quantile()
: 添加分位数回归线geom_rug()
: 边际地毯图geom_smooth()
: 条件均值线geom_text()
: 文本标签
展现分布图
geom_bin2d
:二维热图geom_density2d
:二维密度等高线图geom_hex()
:六边形表示的二维热图
至少一个连续型变量
geom_count
:统计不同地点,点的数量geom_jitter
:给点增加扰动,减轻图形重叠的问题
一个连续变量+一个离散变量
geom_bar(stat = "identity")
:条形图geom_boxplot()
:箱型图geom_violin()
:小提琴图
时间序列+连续变量
geom_area()
: 面积图geom_line()
: 按照x轴坐标大小顺序依次连接各个观测值geom_step()
: 以阶梯的形式连接各个观测值
显示误差或置信区间
geom_crossbar()
: 带水平中心线的盒子图geom_errorbar()
: 误差线+条形图geom_linerange()
: 一条代表一个区间的竖直线geom_pointrange()
: 以一条中心带点的竖直线代表一个区间
地图
geom_map()
5.5.4 三个变量
geom_contour()
: 等高线图geom_tile()
: 瓦片图geom_raster()
: 高效矩形瓦片图
每个几何对象都有其不同的参数,有些是必须的,有些是非必须的,具体请参照ggplot2几何对象以及对应的统计变换和图形属性
5.6 统计变换(stats)
统计变换是指原始数据通过一定的计算或者汇总,以另一种方式呈现。
在不知不觉中,我们已经使用了一些统计变换,实际上它们藏在很多重要的geom命令,例如:
stat_bin()
:geom_bar()
,geom_freqpoly()
,geom_histogram()
stat_bin2d()
:geom_bin2d()
stat_bindot()
:geom_dotplot()
stat_binhex()
:geom_hex()
stat_boxplot()
:geom_boxplot()
stat_contour()
:geom_contour()
stat_quantile()
:geom_quantile()
stat_smooth()
:geom_smooth()
stat_sum()
:geom_count()
我们很少会直接调用这些函数,但是了解它们很有用,因为它们的文档通常会提供有关相应统计变换的更多详细信息。
除此之外,还有很多统计变换是没有包含在函数里的,不能通过geom_
函数使用:
stat_ecdf()
:计算经验累积分布图stat_function()
:添加新函数,根据x值的函数计算y值stat_summary()
:对每个x值所对应的y值做汇总stat_summary2d()
,stat_summary_hex()
:对二维矩形封箱设定函数stat_qq()
:对qqplot图执行计算。stat_spoke()
:将角度和半径转换为位置(xend和yend)stat_unique()
:删除重复值
有两种使用这些功能的方法。可以添加一个stat_()
函数并覆盖默认的geom,也可以添加一个geom_()
函数并覆盖默认的stat:
ggplot(mpg, aes(trans, cty)) + geom_point() + stat_summary(geom = "point", fun.y = "mean", colour = "red", size = 4)ggplot(mpg, aes(trans, cty)) + geom_point() + geom_point(stat = "summary", fun.y = "mean", colour = "red", size = 4)
5.6.1 生成变量(Generated Variables)
实际上,统计变换将数据集作为输入,并返回新的数据集,因此,统计变换可以将新变量添加到原始数据集中。我们可以将美学映射到这些新变量。例如,用于制作直方图的统计变换stat_bin
会产生以下变量:
count
,每个分箱中的观察数density
,每个分箱中的观察密度(占总数的百分比)x
,箱子的中间值
可以使用这些生成的变量代替原始数据集中存在的变量。例如,默认的直方图会将条形的高度分配给观察数(count
),但是如果您更喜欢传统的直方图,则可以使用密度(density
)。要引用生成的变量(density
),则必须在变量名前后加“..
”,避免在原始数据集包含与生成的变量同名的变量的情况下造成混淆,并且可以使以后的代码阅读者都清楚该变量是由统计信息生成的。每个统计信息都列出了在其文档中创建的变量。
例如,钻石数据集(diamonds)中,我们只做price(连续)变量的频率直方图(横轴单位宽度设置为500)。
如下面第一幅图所示,x轴变量是price,而y周变量默认为count(计数);
实际上,如果加以设置,geom_histogram()
函数内部是经过统计变换的,过程中生成density
这个变量。于是在函数geom_histogram()
中增加aws(y = ..density..)
这个设定,就可以将y轴的映射改为stat中间生成的变量density
,如下面第二幅图所示:
ggplot(diamonds, aes(price)) + geom_histogram(binwidth = 500)
ggplot(diamonds, aes(price)) + geom_histogram(aes(y = ..density..), binwidth = 500)
当不同组的大小差异非常大时,很难进行比较。举例来说,以cut分类的不同组,由于有些组观测甚少,直接比较price没有意义:
ggplot(diamonds, aes(price, colour = cut)) + geom_freqpoly(binwidth = 500) +theme(legend.position = "none")
只有通过标准化数据后比较才有意义,而aws(y = ..density..)
恰好就可以调用统计变化生成的新变量,此时y轴是百分比,这样的分布图就就更加清晰了:
ggplot(diamonds, aes(price, colour = cut)) + geom_freqpoly(aes(y = ..density..), binwidth = 500) + theme(legend.position = "none")
5.7 位置调整(Position Adjustments)
位置调整会对图层中元素的位置进行细微调整。
对条形图的位置调整如下:
position_stack()
:将图形(条形、面积)元素堆叠起来position_fill()
:堆叠元素,并将其填充,高度标准化为1position_dodge()
:避免堆叠,并排放置
下图展示了条形图中的三种类型:堆叠stack
、填充fill
、并列dodge
:
dplot <- ggplot(diamonds, aes(color, fill = cut)) + xlab(NULL) + ylab(NULL) + theme(legend.position = "none")dplot + geom_bar()
# position stack is the default for bars, so `geom_bar()` is equivalent to `geom_bar(position = "stack")`.
dplot + geom_bar(position = "fill")
dplot + geom_bar(position = "dodge")
还有一个不执行任何操作的位置调整:position_identity()
。因为每个条形都会遮盖后面的条形,所以可以用透明度来调整。另外,在geom_bar()
函数中可以添加颜色和边框透明度设置:
dplot + geom_bar(position = "identity", alpha = 1 / 2, colour = "grey50")
但是有许多几何图形不需要调整,例如线条:
ggplot(diamonds, aes(color, colour = cut)) + geom_line(aes(group = cut), stat = "count") + xlab(NULL) + ylab(NULL) + theme(legend.position = "none")
对散点图有以下三种位置调整:
position_nudge()
:将每个点移动固定的位移position_jitter()
:添加随机扰动,减少遮盖position_jitterdodge()
:避开组内的点,然后添加一些随机噪声
请注意,将参数传递到位置调整的方式与统计数据和几何图形不同。无需在中添加其他参数...
,而是构造一个位置调整对象,在调用中提供其他参数:
ggplot(mpg, aes(displ, hwy)) + geom_point(position = "jitter")
ggplot(mpg, aes(displ, hwy)) + geom_point(position = position_jitter(width = 0.05, height = 0.5))
上面的代码很冗长,因此geom_jitter()
提供了一个方便的快捷方式:
ggplot(mpg, aes(displ, hwy)) + geom_jitter(width = 0.05, height = 0.5)
连续数据通常不会完全重叠,并且当连续数据重叠时(由于数据密度高),微小的调整(例如抖动)通常不足以解决问题。因此,位置调整通常对于离散数据最有用。
笔记目录:
ggplot2学习笔记1:从qplot()开始
ggplot2学习笔记2:ggplot()语法基础
ggplot2学习笔记3:ggplot()基本用法
ggplot2学习笔记4:绘制几何对象
ggplot2学习笔记5:工具箱(一)基础图层、标签、注释、群组几何对象、曲面图
ggplot2学习笔记6:工具箱(二)误差线、加权数据、展示分布、其他
参考资料:
- 书籍:《ggplot2:数据分析与图形艺术》
- Hadley Wickham(2016). ggplot2. Springer International Publishing. doi: 10.1007/978-3-319-24277-4
ggplot2学习笔记7:通过图层逐层构建图形相关推荐
- ggplot2学习笔记5:工具箱(一)基础图层、标签、注释、群组几何对象、曲面图
此博客作为自己的学习笔记,同时与大家交流分享! Toolbox 首先我们来明确一下使用图层的目的是什么 显示数据(data):绘图时的最底层(数据层),显示数据有助于我们改进模型: 显示数据的统计摘要 ...
- 【AngularJs学习笔记五】AngularJS从构建项目开始
为什么80%的码农都做不了架构师?>>> #0 系列目录# AngularJs学习笔记 [AngularJs学习笔记一]Bower解决js的依赖管理 [AngularJs学习笔 ...
- matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色
一起来学matlab-matlab学习笔记9 高级绘图命令_2 图形的高级控制_视点控制和图形旋转_色图和颜色映像_光照和着色 觉得有用的话,欢迎一起讨论相互学习~ 参考书籍 <matlab 程 ...
- Python学习笔记(二)——Python基本图形绘制
Python学习笔记(二)--Python基本图形绘制 文章目录 Python学习笔记(二)--Python基本图形绘制 不同编程语言的初心和适用对象 Python蟒蛇绘制 五星红旗绘制 这次笔记主要 ...
- ggplot2学习笔记3:ggplot()基本用法
此博客作为自己的学习笔记,同时与大家交流分享! Getting Started with ggplot2 首先明确一下ggplot()画出的图所具备的要素 数据:必须以数据框的形式作为参数 映射:呈现 ...
- ggplot2学习笔记2:ggplot()语法基础
此博客作为自己的学习笔记,同时与大家交流分享! Mastering the Grammar 语法这一部分有点难理解,只是看文字描述的概念不易懂,最好是能在画图过程中去理解体会,只有了解了语法,才能掌握 ...
- 斯坦福大学CS520知识图谱系列课程学习笔记:第二讲如何构建知识图谱
上一讲我们学习了知识图谱的一些基本概念: 斯坦福大学CS520知识图谱系列课程学习笔记:第一讲什么是知识图谱 本节课程关于如何构建知识图谱,因为知识图谱的构建是整个知识图谱领域的一个非常核心且基础的工 ...
- oracle 方泽宇_斯坦福大学CS520知识图谱系列课程学习笔记:第二讲如何构建知识图谱...
上一讲我们学习了知识图谱的一些基本概念:泽宇:斯坦福大学CS520知识图谱系列课程学习笔记:第一讲什么是知识图谱zhuanlan.zhihu.com 本节课程关于如何构建知识图谱,因为知识图谱的构建 ...
- Python3 爬虫学习笔记 C12【验证码对抗系列 — 图形验证码】
Python3 爬虫学习笔记第十二章 -- [验证码对抗系列 - 图形验证码] 文章目录 [12.1]关于普通图形验证码 [12.2]tesserocr 库识别验证码 [12.3]pytesserac ...
最新文章
- win10 应用程序 快捷启动
- PHP Misc. 函数
- asp.net mvc4 配置数据库连接的相关问题
- 密码学 / PKI 体系概述
- JUC多线程:线程池的创建及工作原理 和 Executor 框架
- 为什么Internet选择分组交换而不是电路交换_1012.网络设备:中继器、集线器、网桥、交换机、路由器、网关...
- 如何隐藏SAP Spartacus home页面标准的header区域
- gptuefi优势_UEFI+GPT的区别,有啥不同?写的很详细易懂
- h5是可以一键打包小程序的_H5手机网站封装打包微信小程序并实现分享及微信支付...
- oracle exec编译失效,编译oracle失效的函数、存储过程、视图等
- npm 端口设置成80_13 个 NPM 快速开发技巧
- Sublime Text 3.1.1 Build 3176 注册码破解
- AnyTXT Searcher中文版-比Google Desktop都牛连everything软件作者都拍手称赞的文本搜索工具
- 推送给自学程序员们的一本Python书
- 革新OCR结构化技术应用,揭秘百度中英文OCR结构化模型StrucTexT预训练模型
- 【渝粤教育】广东开放大学 中国文化与中国文学 形成性考核 (46)
- UI设计实用经验分享
- 视频教程-【直通华为HCNA/HCNP系列R篇7】可靠性功能原理及配置与管理-华为认证
- Altium Designer 入门及环境配置
- 20190927CF训练
热门文章
- oa系统php面试问题,oa系统是什么?
- Android 中短信数据库的简单操作
- c语言如何让字符串变成空字符,C语言初始化字符串 c语言 如何将已赋值的字符串初始化为空?...
- 韩国飞中国机票炒至近万元,一票难求
- 内向的孩子学医好还是学计算机好,什么性格适合学医 哪种人不适合学医
- 进销存ERP系统、销售单、采购单、退货单、库存管理、库存盘点、调拨、借入、借出、出库、入库、归还单、收款单、付款单、资金流水、销售报表、采购报表、库存报表、财务报表、商品库、电商erp、连锁erp
- OpenFlow协议初探——OpenFLow中的流和流表
- ffmpeg库编译加文字_我自己的FFMpeg编译之路
- 设计师悲剧:你一天内要完成100张海报
- NRF52840 和电脑 进行蓝牙通信