ggplot2绘图理念
图形系统的核心理念是把绘图与数据分离,把数据相关的绘图与数据无关的绘图分离,按图层作图。ggplot2可以把绘图拆分成多个图层,且能够按照顺序创建多重图形。
由几何对象来控制绘制的几何图形,通过符号“+”来增加图形的元素,这使得绘制图形的过程结构化,同时使绘图更具灵活性。
ggplot2有以下几个特点:
- 有明确的起始(以ggplot函数开始)与终止(一句语句一幅图);
- 图层之间的叠加是靠“+”号实现的,越后面其图层越高。
ggplot图的元素可以主要可以概括如下:最大的是plot(指整张图,包括background和title),其次是axis(包括stick,text,title和stick)、legend(包括backgroud、text、title)、facet这是第二层次,其中facet可以分为外部strip部分(包括backgroud和text)和内部panel部分(包括backgroud、boder和网格线grid,其中粗的叫grid.major,细的叫grid.minor)。大致见下图,这部分内容的熟悉程度直接影响到对于theme的掌握,因此希望大家留心。
一个极具诚意的作图应该长成下面这个样子:
ggplot(data = , aes(x = , y = )) +
geom_XXX(...) + ... +
stat_XXX(...) + ... +
annotate(...) + ... +
scale_XXX(...) + coord_XXX(...) + guides(...) + theme(...)
ggplot2语法框架
在ggplot2中, 图形语法中至少包括了如下几个图形部件,每一个部件可以是一个图层:
-
几何对象(geom)
几何对象控制图层的渲染和生成的图像类型,例如,geom_point()会生成散点图,而geom_line()会生成折线图。
常用的几种几何对象函数:
统计变换(stats)
统计变换是对数据进行统计,通常以某种方式对数据信息进行汇总, 例如通过stat_smooth()添加光滑曲线。-
标度(scale)
通过标度可以修改坐标轴和图例的参数。关于标度,请查看官方文档:Scales 。
最常用的标度是:标签、图形选项(颜色、size、形状、线形等)和坐标轴。
1. 标签
可以通过函数labs()
来指定图形的标题(title),子标题(subtitle),坐标轴的标签(x,y)等,并可以指定标签的美学选项:labs(...)
参数是美学(aesthetic)选项,使用name=value模式,可以使用的选项是:
指定文字:title、subtitle、caption、x和ylabs(title="Automobile Data", x="Weight", y="Miles Per Gallon")
指定美学选项:color、size等
2. 自定义图形选项
scale_fill_manual()
scale_size_manual()
scale_shape_manual()
scale_linetype_manual()
scale_alpha_manual()
scale_discrete_manual()
3,坐标轴
标度是区分离散和连续变量的,标度用于将连续型、离散型和日期-时间型变量映射到绘图区域,以及构造对应的坐标轴。 坐标系(coord)
坐标系统确定x和y美学如何组合以在图中定位元素。默认的坐标系是笛卡尔坐标系,coord_cartesian(),笛卡尔坐标系是最常用的坐标系,函数coord_flip() 用于反转笛卡尔坐标系,把x轴和y轴对调。分面(facet)
分组和分面都用于对数据分组,便于观察各自的规律、趋势和模式,不同的是,分组是把图形绘制到一个大的图形中,通过美学特征来区分,而刻面是把图形绘制到不同的网格中。 分组指的是在一个图形中显示两组或多组观察结果,为了理解数据,在一个图中画出两个或更多组的观察值通常是很有帮助的,在R中,组通常用分类变量的水平(因子)来定义。 分面指的是在单独、并排的图形上显示观察组。 ggplot2包在定义组或面时使用因子。
分面是在一个画布上分布多幅图形,这一过程需要先把数据划分为多个子集, 然后把每个子集依次绘制到画布的不同面板中。
ggplot2提供两种分面类型:网格型(facet_grid)和封面型(facet_wrap)。
网格刻面生成的是一个2维的面板网格, 面板的行与列通过变量来定义, 本质是2维的;
封装刻面则先生成一个1维的面板条块, 然后再分装到2维中, 本质是1维的。-
主题(theme)
主题(Theme)用于控制图形中的非数据元素外观,不会影响几何对象和标度等数据元素,主题主要是对标题、坐标轴标签、图例标签等文字调整, 以及网格线、背景、轴须的颜色搭配。
ggplot图形的主题(theme)元素主要分为5大类:图形(plot)、面板(panel)、坐标轴(axis)、图例(Legend)和带形(Strip),通过theme()
函数来统一控制图形的美学和文本特征,可以用于调整字体,背景色,前景色和网格线等。theme(plot.title = element_text(hjust = 0.5)) #让标题居中
知乎看到一个人的回答,比较好看的主题,备用:
作者:张光耀
链接:https://www.zhihu.com/question/323135094/answer/674152062
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
library(tidyverse)
library(ggthemes)
library(jtools)
library(interactions)
ToothGrowth$dose = factor(ToothGrowth$dose)
Model = lm(data = ToothGrowth, len~supp*dose)
p = interactions::cat_plot(Model, pred = dose, modx = supp, geom = 'line');p
p + ggthemes::theme_calc() # 谷歌办公软件套装
p + ggthemes::theme_economist() # 经济学人杂志
p + ggthemes::theme_few() # 素颜
p + ggthemes::theme_solarized() # 曝光
p + ggthemes::theme_solarized_2() # 曝光2
p + ggthemes::theme_stata() # stata
p + ggthemes::theme_wsj() # 华尔街日报
p + jtools::theme_apa() # APA模板
对于面板的网格线,分为主线(panel.grid.major)和 次线(panel.grid.minor ),用户可以根据绘制图形的需要,显示或隐藏。
关于主题的详细用法,请查看官方文档:Modify components of a theme 和 Theme elements。
Theme()中每一个参数的赋值,可以通过元素函数来实现,margin()
函数用于指定元素的边界,element_xxx用于控制矩形,线条和文本的填充(fill)、颜色,size、形状等。
这些组件之间是通过“+”, 以图层(layer)的方式来粘合构图的,可以这样理解ggplot2中的图层:每个图层可以代表一个图形组件, 这些图形组件以图层的方式叠加在一起构成一个绘图的整体,在每个图层中的图形组件又可以分别设定数据、映射或其他相关参数,因此组件之间又是具有相对独立性的。
常用的图形参数是:
- color:对点、线和填充区域的边界进行着色
- fill:对填充区域着色
- alpha:演示的透明度,从透明(0)到不透明(1)
- linetype:图案的线条(1=实线、2=虚线、3=点、4=点破折号、5=长破折号、6=双破折号)
- size:点的尺寸和线的宽度
- shape:点的形状(和par()函数的pch参数相同)
- position:绘制条形图和点等对象的位置
- binwidth:分箱的宽度
- notch:表示方块图是否应该有缺口
- sides:地毯图的位置("b"=底部、"l"=左部、"r"=右部、"bl"=左下部,等)
-
width:箱线图的宽度
绘图流程
ggplot(data, aes(x = , y = )) + # 基础图层,不出现任何图形元素
geom_xxx()|stat_xxx() + # 几何图层或统计变换,出现图形元素
coord_xxx() + # 坐标变换,默认笛卡尔坐标系
scale_xxx() + # 标度调整,调整具体的标度
facet_xxx() + # 分面,将其中一个变量进行分面变换
guides() + # 图例调整
theme() # 主题系统
共性映射与个性映射
ggplot(data = NULL, mapping = aes())
geom_xxx(data = NULL, mapping = aes())
ggplot()
内有data、mapping两个参数。具有全局优先级,可以被之后的所有geom_xxx对象或stat_xxx()所继承(前提是geom或stat未指定相关参数)。
而geom_xxx()
或stat_xxx()
内的参数属于局部参数,仅仅作用于内部。
为了避免混乱,通常将共性映射的参数指定在ggplot(aes())aes内部,将个性映射的参数指定在geom_xxx(aes())或stat_xxx(aes())内部
ggplot()
ggplot()
用于构造初始的plot对象。主用用来声明画图需要用到的数据框,同时声明图形属性的美学映射(包括坐标轴的映射,x轴是什么,y轴是什么,以及其他一些美学参数等)。
函数ggplot()
可以设置图形,但是没有视觉输出,需要使用一个或多个几何函数向图形中添加几何对象(geometric,简写为geom),包括点(point)、线(line)、条(bar)等,而添加几何图形的格式十分简单,通过符号“+”把几何图形添加到plot中。
语句:
ggplot(data = NULL, mapping = aes(), ..., environment = parent.frame())
解释:
data:数据框对象。默认的用来画图的数据集。需要是data.frame格式的数据。如果不是,需要通过fortify()将其转换为data.frame。如果这里没有指定,则需要在之后绘图的每一个图层都指定。
-
mapping:用于绘图的默认美学映射。如果这里没有指定,则需要在之后绘图的每一个图层都指定。由
aes()
函数来设置映射,aes()函数的功能是指定每个变量扮演的角色(aes代表aesthetics,即如何用视觉美学形式呈现数据信息)。除x和y之外,还有其他美学参数,例如,size、color、shape等,这些参数必须采用name=value的形式。aes参数用来指定要映射的变量,可以是多个变量。
具体可以参见下图和此链接。
…:其他参数。目前还不能使用。
environment:目前已被弃用。调用方法有三种:
- ggplot(df, aes(x, y, other aesthetics))
- ggplot(df)
- ggplot()
如果所有层使用相同的数据和相同的美学映射,推荐使用第一种方法,尽管这种方法也可以使用来自另一个数据框的数据添加层。
第二种方法指定了要用于绘图的默认数据框架,但是没有预先定义美学映射。当一个数据框主要用于添加层时,这是有用的,但美学映射可能因层而异。
第三个方法初始化ggplot对象,该对象在添加层时得到充实。当使用多个数据框来生成不同的层时,这种方法非常有用,在复杂图形中经常如此。
ggplot2 绘制柱形图,也就是所谓的条形图。
一般都需要用到整理好的数据(而不是原始数据)。
如图1所示,每1个x对应一个y,这里可以把y理解为一个汇总后的数据,比如,在A类型下,y的平均值为13。
绘制条形图(geom_bar)
绘制时,必须要声明stat = 'xx',否则语句无法闭合。
ggplot(data = df, mapping = aes(x = x, y = y)) + geom_bar(stat = 'identity')
对于条形图的y轴就是数据框中原本的数值时,必须将geom_bar()函数中stat(统计转换)参数设置为'identity',即对原始数据集不作任何统计变换,而该参数的默认值为'count',即观测数量。
对于没有整理的原始数据,如下图2
这个时候数据没有整理,例如,A类型下,有很多个y值。并不是一个x对应一个y。如果想要直接绘制每种类型(A B C D)出现的频次时,可用如下代码:
ggplot(data = df, mapping = aes(x = x)) + geom_bar(stat = 'count')
数据集本身是明细数据,而对于统计某个离散变量出现的频次时,geom_bar()函数中stat(统计转换)参数只能设置为默认,即'count'。
当然,如果需要对明细数据中的某个离散变量进行聚合(均值、求和、最大、最小、方差等)后再绘制条形图的话,建议先使用dplyr包中的group_by()函数和summarize()函数实现数据汇总。
ggplot2画图注意要点:
aes到底是什么?为什么说任何与数据向量顺序相关,需要逐个指定的参数都必须写在aes里?什么时候color、shape、size、fill写外面,什么时候写里面?
aes实际上做的是将aes里的向量的顺序逐个地绘制。譬如以下代码(转自geom_point帮助文档中的实例):
p <- ggplot(mtcars, aes(wt, mpg)) #<---- code 1
p + geom_point(aes(colour = qsec)) #<---- code 2
结果是:
我们来分析一下ggplot2是怎么作图的。首先,我们来看一下mtcars这个数据集长什么样:
> head(mtcars)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
code 1: ggplot首先载入了这个mtcars的集合,然后指定给了mpg作为其x坐标位置,wt为y坐标位置。
code 2: 指定了qsec作为其染色的标准(分组),qsec为numeric变量,因此,应该选择连续型的标尺,而不是分组染色。然后开始绘制,读取mtcarswt[1],确定位置,然后为其染成mtcars$qsec[1]颜色;再绘制第二点。。。
因此,aes里的美学特征其实就是按照向量顺序指定每个位置的美学特征,大家可以比较tapply函数的写法。
好了,现在问题就来了。我想为所有点的颜色都染成绿色,怎么办?其实很简单,如果不需要指定这么一个染色的顺序,而选择将整个图层染成一种颜色,则只需要将color写在aes外:
p + geom_point(color = "green")
哦,怪不得写在aes里染出来的颜色不是绿色,但为什么写到里面就不可以了,为了写到里面,然出来的是粉色?
好了,我们再来分析一下把color = "green"写到了aes里,到底发生了什么。
p + geom_point(aes(colour = "green"))
首先,数据的初始化跟上面那个例子是相同的。然后,因为color放到了aes里,于是ggplot开始搜索mtcars里面的向量了,发现没有叫"green"的,然后又找了global,也没有。于是,ggplot就开始把它认作了一个新的向量。等等,有个问题,我要按照这个向量来分别染色,而事实上,这个向量长度为1,怎么办?ggplot就先把他展开成了factor(rep("green",nrow(mtcars)),levels = unique("green")),bingo!现在开始染色了。啊第一个数据mtcarswt[1],其颜色变量是"green",因子水平是1,染成默认调色第一种,哦,就是这个蛋蛋的粉红色;再染第二个,还是"green",因子水平也是1,染成蛋蛋的粉红色;... 终于完成了,咦?怎么都是蛋蛋的粉红色。
通过举了这个染色的例子大家应该都弄懂了,aes到底在干什么了。其他的美学特征其实也是完全一致的。只是需要解释group=1的意思就是说不做分组来进行绘图。什么?还是搞不清该放aes里面还是外面?那就记着想统一整个图层时就放到aes外,想分成不同组调整,并且已经有一个与x、y长度一致的分组变量了,那就放到aes里。
这里我个人理解的意思是,如果需要使用data(自己的数据)里面的参数,则需要写在aes内部,如果要统一整个图层,就放在外面。
Rstudio 图片保存
使用Rstudio画图,保存的时候,选择.EPS格式,可以保存矢量图,放大后依旧清晰。可以用AI打开并编辑。但是如果图片涉及到透明度信息,有透明度的图层无法保存,哭唧唧😭。
参考文档:
R绘图 第一篇:ggplot2绘图
美学参数设置
R语言 使用ggplot2进行高级绘图
R语言基础--包的操作与内置数据集
https://danzhuibing.github.io/R_ggplot2.html
手把手教你使用ggplot2绘制条形图
ggplot2-为折线图和条形图添加误差线
ggplot2作分组箱线图并添加均值点连线及显著性程度
R_ggplot2基础(一)
黄宝臣知乎回答