查看原文
其他

圈圈 2018-06-01

ggplot2绘图基础系列:


Build a Plot Layer by Layer

5.1 简介

(略)

5.2 创建图表

(以汽车耗油量mpg数据集为例)

当我们使用 ggplot()创建图表时,最基本的代码是:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point()

实际上这条代码包含了两步命令:

第一个是:

  1. p <- ggplot(mpg, aes(displ, hwy))

它的意义只是创建了一个图层(将这个图层赋予变量p),横纵坐标是数据集 mpg中的两组变量名称 displhwy,但是由于没有命令几何图形,数据无法形成映射,所以就是一块只有横纵坐标的白板↓↓↓↓↓↓

第二个是:

  1. p + geom_point()

在p的基础上,添加函数 geom_point()(散点图),括号是空的就是各种参数都是默认值,于是有了确切的几何图形命令,白板上就有图了↓↓↓↓↓↓

geom_point()这个命令的背后,隐藏着一个叫做 layer()的命令,他的意思是创造一个图层,下面的代码里显示了藏在 layer()里面的各种参数:

  1. p + layer(

  2. mapping = NULL,

  3. data = NULL,

  4. geom = "point",

  5. stat = "identity",

  6. position = "identity"

  7. )

这里面就包括了图层(layer)的五个重要组成部分:

  1. mapping:映射,就是 aes()函数,通常省略,NULL就是指默认的 ggplot()函数中的映射

  2. data:数据,覆盖默认数据集,通常省略,NULL就是默认取 ggplot()中的数据集

  3. geom:几何对象,包含很多美学参数,例如颜色等,在这里设置不会成为标度。

  4. stat:统计变换,执行一些统计汇总,默认设置为 "identity"时保持不变。这个参数在直方图和平滑曲线图中应用较多。 geom和 stat设置一个即可。

  5. position:位置,调整遮盖情况

5.3 数据

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.

ggplot2的作用只是将数据框可视化。在使用之前应该提前整理你的数据框,使其整齐、易于操作(第九章)。

ggplot2的特点在上面的散点图基础上添加一条拟合的曲线:

  1. library(ggplot2)

  2. mpg

  3. mod <- loess(hwy~displ, data = mpg)

  4. grid <- data_frame(displ = seq(min(mpg$displ), max(mpg$displ), length = 50))

  5. grid$hwy <- predict(mod, newdata = grid)

  6. grid

  7. std_resid <- resid(mod) / mod$s

  8. outlier <- filter(mpg, abs(std_resid) > 2)

  9. outlier

  10. ggplot(mpg, aes(displ, hwy)) +

  11.  geom_point() +

  12.  geom_line(data = grid, colour = "blue", size = 1.5) +

  13.  geom_text(data = outlier, aes(label = model))

上述数据处理过程,简化之,可以使用函数 geom_smooth():添加平滑条件均直线,即上面的一大串数据处理过程:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point() +

  3.  geom_smooth(colour = "blue", size = 1.5) +

  4.  geom_text(data = outlier, aes(label = model))

5.4 美学映射(Aesthetic Mappings)

映射的函数就是 aes()。设置数据是怎样对应在到图表上的:

  1. aes(x = displ, y = hwy, colour = class)

x=y= 也可以省略,即放在第一个逗号前的变量默认是x轴,第二个逗号前的变量默认在y轴。

aes()中可以进行一些简单地运算,比如, aes(log(carat),log(price)),但不能出现 美元符号$(例如:diamonds$carat)。

1. 在图表或图层中添加图形属性

这次我们来试试将一个变量映射成一个图形属性——

在上面散点图的基础上,用不同颜色代表不同class(mpg数据集中的离散型变量:

  1. ggplot(mpg, aes(displ, hwy, colour = class)) +

  2.  geom_point()

  3. ggplot(mpg, aes(displ, hwy)) +

  4.  geom_point(aes(colour = class))

  5. ggplot(mpg, aes(displ)) +

  6.  geom_point(aes(y = hwy, colour = class))

  7. ggplot(mpg) +

  8.  geom_point(aes(displ, hwy, colour = class))

实际上,因为图层只有一层,所以以上四种代码意义是一样的,可以画出同样的图表↓↓↓↓↓

但是当图层不只一层之后,参数放在哪里,很重要

比如下面的例子:

映射 aes(colour=class)放在 ggplot函数中:

  1. ggplot(mpg, aes(displ, hwy, colour = class)) +

  2.  geom_point() +

  3.  geom_smooth(method = "lm", se = FALSE) +

  4.  theme(legend.position = "none")

映射 aes(colour=class)只放在 geom_point图层中:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point(aes(colour = class)) +

  3.  geom_smooth(method = "lm", se = FALSE) +

  4.  theme(legend.position = "none")

2. 设定和映射 (Setting vs. Mapping)

除了将图形属性和变量映射(mapping)起来,我们也可以在图层的参数里将其设定(setting)成一个单一值(例如,colour = "read")。

Setting和Mapping是不同的。

例如将上述例子中的图层颜色设置成统一的颜色("darkblue"):

colour="darkblue"直接填写在 point()里即可,不需要在aes()里面设定。

  1. ggplot(mpg, aes(cty, hwy)) +

  2.  geom_point(colour = "darkblue")

否则,如果添加在 aes()里面,它的意义就变成了,将颜色映射到"darkblue"(普通的字符串)上,是用默认的颜色(桃红色)标度进行了转换,就图不达意了:

  1. ggplot(mpg, aes(cty, hwy)) +

  2.  geom_point(aes(colour = "darkblue"))

不过这种方法有时也能用到,比如,如果你想命名两个图层:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point() +

  3.  geom_smooth(aes(colour = "loess"), method = "loess", se = FALSE) +

  4.  geom_smooth(aes(colour = "lm"), method = "lm", se = FALSE) +

  5.  labs(colour = "Method")

5.5 几何图形函数小结

基础命令

  • geom_blank(): 空白,可以用来限制轴的范围

  • geom_point(): 散点

  • geom_path(): 路径

  • geom_ribbon(): 色带图,连续的x值所对应的y值范围

  • geom_segment(): 添加线段或者箭头

  • geom_rect(): 二维矩形图

  • geom_polyon(): 填充多边形

  • geom_text(): 文本注释

一个变量

离散型变量
  • geom_bar():

连续型变量
  • geom_histogram(): 直方图

  • geom_density(): 光滑密度曲线图

  • geom_dotplot(): 点直方图

  • geom_freqpoly(): 频率多边形图

两个变量

都是连续的
  • 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()

三个变量

  • geom_contour(): 等高线图

  • geom_tile(): 瓦片图

  • geom_raster(): 高效矩形瓦片图

5.6 统计变换(stat)

统计变换是指原始数据通过一定的计算或者汇总,以另一种方式呈现。

在不知不觉中,我们已经使用了一些统计变换,实际上它们藏在很多重要的geom命令里,比如:

除此之外,还有很多统计变换是没有包含在函数里的,不能通过 geom_函数使用:

  • stat_ecdf():经验累积分布函数

  • stat_function():添加新函数

  • stat_summary():对每个x值所对应的y值做汇总

  • stat_summary2d()stat_summary hex():对二维矩形封箱设定函数

  • stat_qq():计算qqplot图的相关值

  • stat_spoke():将角度和半径转换成xend和yend

  • stat_unique():删除重复值

以下两种代码生成的图是一样的,使用示例:

  1. ggplot(mpg, aes(trans, cty)) +

  2.  geom_point() +

  3.  stat_summary(geom = "point", fun.y = "mean", colour = "red", size = 4)

  1. ggplot(mpg, aes(trans, cty)) +

  2.  geom_point() +

  3.  geom_point(stat = "summary", fun.y = "mean", colour = "red", size = 4)

生成变量(Generated Variables)

stat的后台操作是将一个你输入的数据集(依据某种命令)转换成一个新的数据集输出,因此stat会在原有数据的基础上增加一些新的变量。

例如,直方图 geom_histogram()中用到的 stat_bin()就会产生下面三个变量:

  1. count:每个条形中观测值的个数

  2. density:每个条形中观测值的密度(占总数的百分比)

  3. x:中间值

有时候通过stat产生的变量可以替代原始数据集中的简单变量

例如,钻石数据集(diamonds)中,我们只做price(连续)变量的频率直方图(横轴单位宽度设置为500):

  1. ggplot(diamonds, aes(price)) +

  2.  geom_histogram(binwidth = 500)

x轴变量是price,而y周变量默认为count(计数):

实际上,如果加以设置, geom_histogram()函数内部是经过统计变换的,过程中生成 density这个变量。于是在函数 geom_histogram()中增加 aws(y=..density..)这个设定,就可以将y轴的映射改为stat中间生成的变量 density

  1. ggplot(diamonds, aes(price)) +

  2.  geom_histogram(aes(y = ..density..), binwidth = 500)

当你想观察多组的组间分布,而这些小组本身分布就不均匀的时候,这种方法很重要:

  1. ggplot(diamonds, aes(price, colour = cut)) +

  2.  geom_freqpoly(binwidth = 500) +

  3.  theme(legend.position = "none")

要观察各个价位不同cut类型钻石的个数,但是有的cut类型的钻石总数就很少,有的总数就很多,这种情况下,当y轴为普通计数时,那些总数较少的类别的钻石数量就几乎看不到了

如果修改一下代码:

  1. ggplot(diamonds, aes(price, colour = cut)) +

  2.  geom_freqpoly(aes(y = ..density..), binwidth = 500) +

  3.  theme(legend.position = "none")

如果y轴是百分比,这样的分布图就就更加清晰了↓↓↓↓↓↓

5.7 位置调整(Position Adjustments)

位置调整主要用于调整图层中微小元素的微调。

  • position_stack(): 将图形(条形、面积)元素堆叠起来

  • position_fill(): 堆叠元素,并将其填充,高度标准化为1

  • position_dodge(): 避免堆叠,并排放置

条形图中可以很容易看出不同类型的位置调整。下图展示了三种类型:堆叠(stack)、填充(fill)、并列(dodge)。

  1. dplot <- ggplot(diamonds, aes(color, fill = cut)) +

  2.  xlab(NULL) + ylab(NULL) + theme(legend.position = "none")

  3. dplot + geom_bar()    #position stack is the default for bars, so `geom_bar()` is equivalent to `geom_bar(position = "stack")`

  4. dplot + geom_bar(position = "fill")

  5. dplot + geom_bar(position = "dodge")

我理解的是,

堆叠就是相同的x坐标,一个条形放到另一个上面

填充就是再堆叠的基础上高度标准化

并列更像是一种分类


还有一种叫做 position_identity(),意思是原地不动。

另外,在 geom_bar()函数中可以添加颜色和边框透明度设置

  1. dplot <- ggplot(diamonds, aes(color, fill = cut)) +

  2.  xlab(NULL) + ylab(NULL) + theme(legend.position = "none")

  3. dplot + geom_bar(position = "identity", alpha = 1 / 2, colour = "grey50")

散点图中的位置调整主要有以下三个函数:

  • position_nudge(): 将每个点移动固定的位移

  • position_jitter(): 添加随机扰动,减少遮盖

  • position_jitterdodge(): 闪避组内的点

例如:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point(position = "jitter")

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_point(position = position_jitter(width = 0.05, height = 0.5))

扰动点图,可以简写成以下代码:

  1. ggplot(mpg, aes(displ, hwy)) +

  2.  geom_jitter(width = 0.05, height = 0.5)

参考资料:

  1. Hadley Wickham(2016). ggplot2. Springer International Publishing. doi: 10.1007/978-3-319-24277-4

  2. 《R语言应用系列丛书·ggplot2:数据分析与图形艺术》

快快和我一起上车,请关注:生信小白学习记

猜你喜欢

10000+:肠道细菌 人体上的生命 宝宝与猫狗 梅毒狂想曲 提DNA发Nature 实验分析谁对结果影响大  Cell微生物专刊

系列教程:微生物组入门 Biostar 微生物组  宏基因组

专业技能:生信宝典 学术图表 高分文章 不可或缺的人

一文读懂:宏基因组 寄生虫益处 进化树

必备技能:提问 搜索  Endnote

文献阅读 热心肠 SemanticScholar Geenmedical

扩增子分析:图表解读 分析流程 统计绘图

16S功能预测   PICRUSt  FAPROTAX  Bugbase Tax4Fun

在线工具:16S预测培养基 生信绘图

科研经验:云笔记  云协作 公众号

编程模板 Shell  R Perl

生物科普  生命大跃进  细胞暗战 人体奥秘  

写在后面

为鼓励读者交流、快速解决科研困难,我们建立了“宏基因组”专业讨论群,目前己有国内外150+ PI,1300+ 一线科研人员加入。参与讨论,获得专业解答,欢迎分享此文至朋友圈,并扫码加主编好友带你入群,务必备注“姓名-单位-研究方向-职称/年级”。技术问题寻求帮助,首先阅读《如何优雅的提问》学习解决问题思路,仍末解决群内讨论,问题不私聊,帮助同行。

学习16S扩增子、宏基因组科研思路和分析实战,关注“宏基因组”

点击阅读原文,跳转最新文章目录阅读

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存