从零开始学画图
hi,大家好,我是晨曦,接收到很多小伙伴们的反馈,希望出一些专门的绘图教程既可以巩固我们的R语言基础,同时又可以提高我们的可视化能力~
所以,它来了!
这期的从零开始绘图的教程将带领大家彻底掌握ggplot2的绘图逻辑,而且这款教程是ggplot2的作者亲笔书写:https://ggplot2-book.org/facet.html
在这里我们将跳过篇幅漫长的理论,以最直观的方式——直接实践,来帮助大家快速掌握可视化技能!
相信跟完这一系列教程对于大家的R语言功底一定会有一个不小的提高,那么话不多说,我们就开始吧。
晨曦单细胞笔记系列传送门
#准备工作library(ggplot2)mpg#> # A tibble: 234 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 audi a4 1.8 1999 4 auto(l5) f 18 29 p compa…#> 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compa…#> 3 audi a4 2 2008 4 manual(m6) f 20 31 p compa…#> 4 audi a4 2 2008 4 auto(av) f 21 30 p compa…#> 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compa…#> 6 audi a4 2.8 1999 6 manual(m5) f 18 26 p compa…#> # … with 228 more rows
晨曦解读
相信大家都知道,我们绘图的第一步,肯定是准备输入数据,所以了解输入数据无非就是我们可视化过程中最重要的一步
晨曦解读
每一个ggplot2绘制的图都会有三个关键的因素
1. 数据(data)
2. 设置变量之间的映射关系
3. 展示映射关系的方式(通常使用geom函数创建)
#exampleggplot(mpg, aes(x = displ, y = hwy)) + geom_point()
晨曦解读
1. data——mpg
2. 映射关系——X变量(displ)和Y变量(hwy)
3. 展示映射关系的方式——geom_point函数(点图)
请注意,ggplot2以图层的形式构建整个绘图函数,以“+”连接每个图层
提问:图层该如何理解?
图层即美图秀秀,首先我们P个瘦脸作为第一图层,P个大眼睛作为第二图层,P个磨皮作为第三图层,最后得到的图片就是三个图层的相叠加起来。
提问:图层之间有无先后顺序?
一般以最后的图层为主,这就是全局映射和局部映射的区别。
可以简单解释为美国有联邦法院,联邦法院颁布的法令适用整个美国,但是美国各个洲也有各自的规定适用于各洲,当联邦法令和洲法令相矛盾的时候,听从每个洲的法令,这就是全局映射和局部映射的区别。
另外,aes参数默认,第一个实际参数为变量X,第二个实际参数为变量Y,所以下面的代码和上面的代码表达的是同一个意思。
ggplot(mpg, aes(displ, hwy)) + geom_point()
晨曦解读
到这里,我们完成了ggplot2绘图基本三要素的讲解,是不是感觉对于绘图,其实也不是很难呢?
当然在这个看脸的时代,这么的朴实无华肯定会少了些许夺人眼球的魅力,所以我们接下来就要装饰我们的可视化,让它具有妖娆美丽的身姿~
#ggplot2优秀的地方在于,你只需要告诉它数据在哪里,它就可以自动的进行后续一系列的修饰#比如说,我告诉它,请按照class变量给我设计颜色ggplot(mpg, aes(displ, hwy, colour = class)) + geom_point()
晨曦解读
可视化是不是一下子就好看了呢?!
当然我们也可以自己设置颜色
ggplot(mpg, aes(displ, hwy)) + geom_point(aes(colour = "blue"))ggplot(mpg, aes(displ, hwy)) + geom_point(colour = "blue")
晨曦解读
上面两个代码有什么区别呢?
欢迎大家在评论区讨论哦~
这里我也提供给大家关于ggplot2的更多修饰参数,方便大家进一步学习
https://ggplot2.tidyverse.org/articles/ggplot2-specs.html
下面我们再来进行更多的探索
如果我想一个代码出现两张图,那么接下来的分析手段你可能千万不要错过
ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~class)
晨曦解读
分面对于刚接触ggplot2的小伙伴来说,可能算的上是一个难点了
这里我简单解释一下,分面其实就是又设计了一个绘图分组的因素
比如说我们这个图是横坐标displ,纵坐标是hwy,然后这两个变量绘制散点图,在这个散点图的基础上在把这些点对应的不同class挑出来单独成图,这就是分面
适用于两个变量之间相关性的比较时这两个变量又对应不同分组的时候
下面我们继续
ggplot2提供给我们了很多绘图的函数
这些函数有一个大致的共同点
geom_smooth函数、geom_boxplot函数、geom_histogram函数等等,大多数都是geom开头的
更多的函数可以参考下面这个ggplot2小抄来进行更多的学习
Function reference • ggplot2 (tidyverse.org)
接下来我们将在相关性点图上添加拟合曲线
ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth()
晨曦解读
我在这里将展现一下我学函数的一般逻辑。
geom_smooth函数,默认参数为使用loess方法,以横坐标为自变量,纵坐标为因变量进行拟合曲线的绘制。
但是这个置信区间的阴影我不想要,该怎么办?
这里我们需要想到局部和全局的关系,我们可以这么改动
ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(se=FALSE)
逻辑即先明确默认参数,然后在需求的推动下,有选择的进行参数的学习
其次拟合曲线中还有一个很重要的参数就是method参数的选择
#请观察下面的代码,并尝试在自己的电脑上运行ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(span = 0.2)#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(span = 1)#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
晨曦解读
span参数可以调节曲线的抖动情况,参数的选择范围在0(非常抖动)——1(非常平稳)
#当我们需要线性拟合的时候,可以尝试修改method参数ggplot(mpg, aes(displ, hwy)) + geom_point() + geom_smooth(method = "lm")#> `geom_smooth()` using formula 'y ~ x'
晨曦解读
了解完点图的大致绘制方法后,我们接下来再学习一个我们常常接触到的可视化方式
箱线图
ggplot(mpg, aes(drv, hwy)) + geom_point()
晨曦解读
接下来我们运用同样的数据进行三个图的绘制
ggplot(mpg, aes(drv, hwy)) + geom_jitter()ggplot(mpg, aes(drv, hwy)) + geom_boxplot()ggplot(mpg, aes(drv, hwy)) + geom_violin()
晨曦解读
ggplot2语法相通,所以针对上图进行DIY也是前面的基础内容哦~
下面我们来进行一下直方图的学习
ggplot(mpg, aes(hwy)) + geom_histogram()#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.ggplot(mpg, aes(hwy)) + geom_freqpoly()#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
提问:为什么这里映射只选择了一个变量,那另一个变量是从哪里来的呢
这里我们就需要了解到ggplot2里的函数大致可以用两大功能
一个是可视化(几何对象函数),一个则是统计(统计变换函数)
我们通过指定一个变量,函数就可以帮助我们计算出这个变量的数量,即count
#请仔细观察下面这两个可视化ggplot(mpg, aes(hwy)) + geom_freqpoly(binwidth = 2.5)ggplot(mpg, aes(hwy)) + geom_freqpoly(binwidth = 1)
晨曦解读
当我们看帮助文档后仍然无法彻底理解某个参数的时候,可以尝试这样的方法来进行参数的学习,相信通过上面的可视化对比,大家应该可以很直观的感受到binwidth参数的用处
可能会有小伙伴会问,老师这些简单的图也放不到文章里,我学他们干什么?
那么下面我将用基础代码来绘制一个美图
ggplot(mpg, aes(displ, colour = drv)) + geom_freqpoly(binwidth = 0.5)ggplot(mpg, aes(displ, fill = drv)) + geom_histogram(binwidth = 0.5) + facet_wrap(~drv, ncol = 1)#上面这两个图用patchwork包拼起来然后就是一张精致的美图了
晨曦解读
接下来我们再来讲解一些常用的geom_xx函数
首先是直方图
ggplot(mpg, aes(manufacturer)) + geom_bar()
晨曦解读
当然有的时候我们有自己的Y轴,也就是说我不想让我们的函数行使统计功能,我只想让ggplot2函数行使可视化功能,那么我们可以通过修改stat函数来完成我们的目标
#输入数据drugs <- data.frame( drug = c("a", "b", "c"), effect = c(4.2, 9.7, 6.1))#可视化ggplot(drugs, aes(drug, effect)) + geom_bar(stat = "identity")ggplot(drugs, aes(drug, effect)) + geom_point()
提问:为什么这里没用参数修改的代码不选择geom_bar函数?
因为这个函数内置统计变换函数的算法,所以我们如果不设置stat参数,就会进行统计,但是我们设置的输入数据是一个没有重复的数据,所以计数结果是0,无法可视化,所以会出现报错。
从这里我们知道,ggplot2不是所有的函数都有统计变换的功能,可以简单认为大多数直方图或者是柱状图有这类功能即可,或者可以看该绘图函数内有无stat参数也是一种不错的办法。
接下来我们来探索,如果我们想要绘制某数值随时间变化的可视化结果,那下面的代码会帮助到你。
ggplot(economics, aes(date, unemploy / pop)) + geom_line()ggplot(economics, aes(date, uempmed)) + geom_line()
晨曦解读
这种具有时间改变的数据,折线图在这里还是非常实用的
那么下面我们开始学习一下如何对我们已经绘制的可视化结果进行一些修改
ggplot(mpg, aes(cty, hwy)) + geom_point(alpha = 1 / 3)ggplot(mpg, aes(cty, hwy)) + geom_point(alpha = 1 / 3) + xlab("city driving (mpg)") +  ylab("highway driving (mpg)")# Remove the axis labels with NULLggplot(mpg, aes(cty, hwy)) + geom_point(alpha = 1 / 3) + xlab(NULL) + ylab(NULL)
晨曦解读
alpha参数能调节点的颜色深浅
xlab函数和ylab函数可以设置横纵坐标的Symbol
#请自行学习下面的代码#并且探索xlim函数和ylim函数的用途ggplot(mpg, aes(drv, hwy)) + geom_jitter(width = 0.25)ggplot(mpg, aes(drv, hwy)) + geom_jitter(width = 0.25) + xlim("f", "r") + ylim(20, 30)#> Warning: Removed 140 rows containing missing values (geom_point).# For continuous scales, use NA to set only one limitggplot(mpg, aes(drv, hwy)) + geom_jitter(width = 0.25, na.rm = TRUE) + ylim(NA, 30)
提问:为什么设置NA?
NA的设置在于我们可以让函数自行适配合适的最低标度,这里只支持一头设置,比如ylim(NA,30)或者ylim(10,NA)这都是可以的,但是如果都是NA,让函数自行判断最高和最低标度,函数就会报错,因为你最起码需要提供给R一个标度才可以。
接下来我们把可视化结果导出,来作为我们今天教程的结尾
p <- ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) + geom_point()#在R中查看print(p)#导出ggsave("plot.png", p, width = 5, height = 5)#查看作图细节summary(p)#> data: manufacturer, model, displ, year, cyl, trans, drv, cty, hwy, fl,#> class [234x11]#> mapping: x = ~displ, y = ~hwy, colour = ~factor(cyl)#> faceting: <ggproto object: Class FacetNull, Facet, gg>#> compute_layout: function#> draw_back: function#> draw_front: function#> draw_labels: function#> draw_panels: function#> finish_data: function#> init_scales: function#> map_data: function#> params: list#> setup_data: function#> setup_params: function#> shrink: TRUE#> train_scales: function#> vars: function#> super: <ggproto object: Class FacetNull, Facet, gg>#> -----------------------------------#> geom_point: na.rm = FALSE#> stat_identity: na.rm = FALSE#> position_identity#保存成空间变量saveRDS(p, "plot.rds")#读取空间变量q <- readRDS("plot.rds")
提问:什么是空间变量?
下面这个图就是空间变量
好啦,今天我们ggplot2绘图讲解到这里就告一段落了。
依旧是熟悉的保姆式教学,相信大家只要一直跟住大队伍,不会过太长时间,大家就都会成为R语言可视化小能手哦~
回顾一下,今天我们其实学的就只有一个东西:ggplot2的基础参数以及基础绘图
基础不牢,地动山摇
欢迎大家在评论区打卡学习成果(学习思路、学习心得、学习进程等等都可以~)
打卡积极的同学会有神秘惊喜哦~
我是晨曦,我们下次再见~
主页回复“晨曦可视化01,即可获得今天的范例数据和代码哦~
END

撰文丨晨   曦
排版丨四金兄
主编丨小雪球
欢迎大家关注解螺旋生信频道-挑圈联靠公号~
继续阅读
阅读原文