R笔记之ggplot2画图

ggplot2绘图理念

图形系统的核心理念是把绘图与数据分离,把数据相关的绘图与数据无关的绘图分离,按图层作图。ggplot2可以把绘图拆分成多个图层,且能够按照顺序创建多重图形。
由几何对象来控制绘制的几何图形,通过符号“+”来增加图形的元素,这使得绘制图形的过程结构化,同时使绘图更具灵活性。

ggplot2有以下几个特点:

  1. 有明确的起始(以ggplot函数开始)与终止(一句语句一幅图);
  2. 图层之间的叠加是靠“+”号实现的,越后面其图层越高。

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的掌握,因此希望大家留心。


image.png

一个极具诚意的作图应该长成下面这个样子:

ggplot(data = , aes(x = , y = )) + 
geom_XXX(...) + ... + 
stat_XXX(...) + ... +
annotate(...) + ... +
scale_XXX(...) + coord_XXX(...) + guides(...) + theme(...)

ggplot2语法框架

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和y

    labs(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 themeTheme 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参数相同)
shape点的形状
  • position:绘制条形图和点等对象的位置
  • binwidth:分箱的宽度
  • notch:表示方块图是否应该有缺口
  • sides:地毯图的位置("b"=底部、"l"=左部、"r"=右部、"bl"=左下部,等)
  • width:箱线图的宽度
    几何函数的常见选项

    image.png

    image.png

绘图流程

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参数用来指定要映射的变量,可以是多个变量。
    具体可以参见下图和此链接

    映射mapping

    …:其他参数。目前还不能使用。
    environment:目前已被弃用。

    调用方法有三种:

    1. ggplot(df, aes(x, y, other aesthetics))
    2. ggplot(df)
    3. ggplot()
      如果所有层使用相同的数据和相同的美学映射,推荐使用第一种方法,尽管这种方法也可以使用来自另一个数据框的数据添加层。
      第二种方法指定了要用于绘图的默认数据框架,但是没有预先定义美学映射。当一个数据框主要用于添加层时,这是有用的,但美学映射可能因层而异。
      第三个方法初始化ggplot对象,该对象在添加层时得到充实。当使用多个数据框来生成不同的层时,这种方法非常有用,在复杂图形中经常如此。

ggplot2 绘制柱形图,也就是所谓的条形图。

一般都需要用到整理好的数据(而不是原始数据)。
如图1所示,每1个x对应一个y,这里可以把y理解为一个汇总后的数据,比如,在A类型下,y的平均值为13。

图1

绘制条形图(geom_bar

绘制时,必须要声明stat = 'xx',否则语句无法闭合。
ggplot(data = df, mapping = aes(x = x, y = y)) + geom_bar(stat = 'identity')
对于条形图的y轴就是数据框中原本的数值时,必须将geom_bar()函数中stat(统计转换)参数设置为'identity',即对原始数据集不作任何统计变换,而该参数的默认值为'count',即观测数量。
对于没有整理的原始数据,如下图2

图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

结果是:


image.png

我们来分析一下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变量,因此,应该选择连续型的标尺,而不是分组染色。然后开始绘制,读取mtcarsmpg[1]、mtcarswt[1],确定位置,然后为其染成mtcars$qsec[1]颜色;再绘制第二点。。。
因此,aes里的美学特征其实就是按照向量顺序指定每个位置的美学特征,大家可以比较tapply函数的写法。
好了,现在问题就来了。我想为所有点的颜色都染成绿色,怎么办?其实很简单,如果不需要指定这么一个染色的顺序,而选择将整个图层染成一种颜色,则只需要将color写在aes外:

p + geom_point(color = "green") 

哦,怪不得写在aes里染出来的颜色不是绿色,但为什么写到里面就不可以了,为了写到里面,然出来的是粉色?


image.png

好了,我们再来分析一下把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!现在开始染色了。啊第一个数据mtcarsmpg[1]、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基础(一)
黄宝臣知乎回答

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容