19. ggplot2快速入门

1. Introduce

ggplot2是R语言最流行的第三方扩展包,是RStudio首席科学家Hadley Wickham读博期间的作品,是R相比其他语言一个独领风骚的特点.包名中"gg"是grammar of graphics的简称,是一套优雅的绘图语法.

比较有条理的快速入门Click.

ggplot2这门绘图语言提供了一组概念.

  • 数据:data
  • 统计变换:stats
  • 几何对象:geom
  • 图形属性:aes
  • 标尺:scale
  • 图层:layer
  • 坐标系:coord
  • 分面:facet

我们举个具体的例子来解读这些概念.假设现在我们要对一批连续取值的数据绘制直方图.首先,要定义清楚需要几个分组或者每个分组的区间,根据分组定义统计落在这个分组里的个数,这个步骤就是把data 变为stats .然后,需要选定表达数据的几何对象,这个例子选用的是条块bar,这个步骤就是选geom .geom 有一堆属性需要设定,比如x、y、颜色等,称为aes ,哪个aes 由哪个stats 指定,需要指定一个映射关系mapping ,即指定谁对谁.知道谁对谁后,还需要知道怎么个对法,需要由scale 决定,比如stats的color字段取值为1应该对到什么颜色上,取值为2应该对到什么颜色上.这些完成了以后,统计图形的主体部分就成形了,但是假如我们希望在直方图上,再画一个概率密度曲线图,怎么办?ggplot2的思想非常精妙,把上面的主体部分称为一个图层layer ,一个统计图形可以拥有多个图层,每个图层叠加起来形成我们要的效果。接下来,再选定一个坐标系统coord ,一张统计图形plot 就做好了.假如我们有多组数据,每组数据都要按照相同的方法画一张图,每张图重复敲代码很繁琐,就可以使用分面facet快速绘制多张统计图形。这个过程用图形总结如下:

2. Example: volcano plot

现在我们重新绘制火山图.

2.1 导入数据

火山图使用的数据是差异表达数据.

R 复制代码
deg_table = read.table(file = '24.DE_analysis/merge.DE_results',sep = '\t',header=T)
head(deg_table)

火山图只允许两组之间比较,所以要进行过滤.

R 复制代码
filter(deg_table,sampleA=='Cs2',sampleB=='Cs1') %>% 
  arrange(desc(abs(log2FoldChange))) -> deg_sort
head(deg_sort)

2.2 绘图

类似matplotlib,我们绘图首先可以先创建一个画布.

R 复制代码
library(ggplot2)
ggplot(
  data=deg_sort,
  mapping = aes(x=log2FoldChange,y=padj)
)

接下来,把点画上去.也就是添加几何对象.但是注意一下, <math xmlns="http://www.w3.org/1998/Math/MathML"> y y </math>y轴按火山图需要取 <math xmlns="http://www.w3.org/1998/Math/MathML"> − l o g 10 -log_{10} </math>−log10.

R 复制代码
ggplot(
  data=deg_sort,
  mapping = aes(x=log2FoldChange,y=-log10(padj))
) + 
  geom_point()#+表示加一个图层

接下来,是用颜色区分上下调、非差异基因的点.也就是上一节我们direction那一列映射到不同颜色.我们先把列构造出来.
一个坑爹的点,R使用&&或者||会让一些包运行报错,所以只能使用&或者|
python果然天下第一

R 复制代码
select(deg_sort,gene_id,sampleA,sampleB,log2FoldChange,pvalue,padj) %>%
  mutate(direction = if_else(abs(log2FoldChange)>=1 & padj <= 0.05,
                             if_else(log2FoldChange >=1,'Up','Down'),'NS')) -> deg_direction

head(deg_direction)
R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))
) + #aes表示映射
  geom_point(aes(color=direction))

ggplot2允许更换背景图.背景图也是一个图层.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))
) + #aes表示映射
  geom_point(aes(color=direction)) +
  theme_dark()

2.3 中期总结

我们说的几何对象,实际是指要画什么图,比如柱状、条状等等.ggplot2提供了众多几何对象geom_xyz()供大家选择。举两个常见的例子,geom_point()用于表示两个连续变量之间的关系,几何形状是点;geom_bar()用于表示x轴为离散变量,y轴为连续连续变量之间的关系,几何形状是条块.

每个几何对象都有自己的属性,这些属性的取值需要通过数据提供。数据与图形属性之间的映射关系称为mapping ,在ggplot2中用aes()进行定义。常见的图形属性有:xysizecolorgroup。图形属性的任意一项都可以用数据的某一个变量来表示。

ggplot2的绘图过程有点像Photoshop,有一个图层的理念,每个图层可以有自己的图形对象和图形属性,通过+将不同图层叠加起来生成最后的统计图形.如果将数据定义在ggplot()中,那么所有图层都可以共用这个数据;如果将数据定义在geom_xyz()中,那么这个数据就只供这个几何对象使用.

3. Scale 与 mapping

前面提到aes()设定了数据与图形属性的映射关系,但是数据怎么映射为属性,这就是标尺(Scales)的功能.

3.1 Example: Point Size

我们用上面的例子,举例一下设置点的大小.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))
) + #aes表示映射
  geom_point(aes(color=direction),size =3) +
  theme_dark()

这里理解一下设置和映射的区别.我们写在aes里的就是定义映射关系,而上面代码我们写在aes外,就是设置全部点的大小都是3.

3.2 Example: legend sequence

看上图可以发现,图例的字符串是按字典序进行排列的.但如果我们要重新排序,就需要使用factor,这里的factor像是定义我们的排序规则.具体看代码.但实际上它是存储类别的数据,它定义一组数据的类别.

这里有篇简单教程ClickClick.

R 复制代码
x = c('top','up','mask','mask','top','up')
# 按字典排序.
sort(x)
# "mask" "mask" "top"  "top"  "up"   "up"  
y = factor(x,levels=c('up','top','mask'))
sort(y)
[1] up   up   top  top  mask mask
Levels: up top mask

那么我们重新定义direction的顺序.

R 复制代码
select(deg_sort,gene_id,sampleA,sampleB,log2FoldChange,pvalue,padj) %>%
  mutate(direction = if_else(abs(log2FoldChange)>=1 & padj <= 0.05,
                             if_else(log2FoldChange >=1,'Up','Down'),'NS')) %>%
  mutate(direction = factor(direction,levels=c('Up','Down','NS'))) -> deg_direction
  #mutate修改列

# 重新画图,会发现顺序变了
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))
) + #aes表示映射
  geom_point(aes(color=direction),size =3) +
  theme_dark()

我们把列提取出来,会发现类型变了.

R 复制代码
class(deg_direction$direction)
#factor

3.3 Example: Scale and color

接下来调整图例的颜色.这就涉及到scale.对于任何一个图形属性,如x,y,alpha,color,fill,linetype,shape,size,ggplot2都提供以下四种标尺.

  • scale_*_continuous():将数据的连续取值映射为图形属性的取值
  • scale_*_discrete():将数据的离散取值映射为图形属性的取值
  • scale_*_identity():使用数据的值作为图形属性的取值
  • scale_*_mannual():将数据的离散取值作为手工指定的图形属性的取值

在对图形属性进行映射之后,使用标尺可以控制这些属性的显示方式,比如坐标刻度,颜色属性等.

从下面代码来看,我们先是映射了不同direction值和color之间的关系,但是要具体指定关系需要用scale指明.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction),size =3) +
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  theme_dark()
  #这里将离散数值映射到图像属性

4. axis modify

4.1 axis scale

修改坐标轴的大小.其实是修改break参数.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange))) +
  scale_color_manual(values = c('red','blue','grey'),name = 'difference express condition') +
  scale_size(range = c(0.3,4),name = '|log2FoldChange|') + #规定了点的大小范围
  scale_x_continuous(name = "log2(Fold Change)",breaks = seq(-5,5,1)) + 
  scale_y_continuous(name = "-log10(pvalue)") + 
  theme_dark()
  #这里将离散数值映射到图像属性

4.2 title modify

标题在ggplot2里,也叫引导元素,标题其实是修改X轴的映射方式.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange))) +
  scale_color_manual(values = c('red','blue','grey'),name = 'difference express condition') +
  scale_size(range = c(0.3,4),name = '|log2FoldChange|') + #规定了点的大小范围
  scale_x_continuous(name = "log2(Fold Change)",breaks = seq(-5,5,1)) + 
  scale_y_continuous(name = "-log10(pvalue)") + 
  theme_dark()
  #这里将离散数值映射到图像属性

修改title其实有更简单的写法,但是本质还是上面的修改方式.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange))) +
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

4.3 delete legends

我们也可以删除图例,使用show.legend = F.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

5. 几何对象修改

5.1 添加参考线

举个例子,我们先横线,就需要添加geom_hline函数,并使用yintercept指定它的位置.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_hline(yintercept = -log10(0.05))+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

也可以修改线的样式.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash")+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

接下来添加竖线,竖线需要添加两条,也就是使用geom_vline函数.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

5.2 添加标签

已知新图层会继承背景图层的数据和映射关系.因为我们把aes(x=...,y=...)映射到背景图上,所以后面的图不需要指定x,y轴.   当我们想给每个点添加标签时,会继承背景图层的数据,也就是给背景图层的数据都加上标签,如果要修改必须重新赋值data.

R 复制代码
ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_text(aes(label=gene_id)) +#如果前面背景图没有指定x,y轴,这里就需要指定x,y轴
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

  画出来的图很辣眼睛,因此需要只选择一部分来画.这里只选择了前10个.

R 复制代码
key_genes = c(deg_direction$gene_id[1:10])

ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_text(data=filter(deg_direction,gene_id==key_genes),aes(label=gene_id)) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性
  
#filter(deg_direction,gene_id %in% key_genes) 用这个也行

  也可以将标签加到同色.主要是在映射处给color赋值.

R 复制代码
library(ggrepel)
key_genes = c(deg_direction$gene_id[1:10])

ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_text_repel(data=filter(deg_direction,gene_id==key_genes),size=3,aes(label=gene_id,color=direction),show.legend = F) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

5.3 添加扰动

上图可以发现label挡住了部分点,因此需要将label挪动一下位置,这种我们一般使用ggrepel包.然后使用geom_text_repel.

R 复制代码
library(ggrepel)
key_genes = c(deg_direction$gene_id[1:10])

ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_text_repel(data=filter(deg_direction,gene_id==key_genes),aes(label=gene_id)) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

5.4 添加黑框

我们可以给关键基因添加黑框,方便观察.黑框的本质也是在背景图上加点,同时我们shape是用于指定形状.stroke是调整厚度.可以参考这个Click.

R 复制代码
library(ggrepel)
key_genes = c(deg_direction$gene_id[1:10])

ggplot(
  data=deg_direction,
  mapping = aes(x=log2FoldChange,y=-log10(padj))) + #aes表示映射
  geom_point(aes(color=direction,size=abs(log2FoldChange)),show.legend = F) +
  geom_point(data=filter(deg_direction,gene_id==key_genes),shape=21,color='black',
             aes(fill=direction,size=abs(log2FoldChange),stroke=2),show.legend = F
             )+
  geom_text_repel(data=filter(deg_direction,gene_id==key_genes),size=3,aes(label=gene_id,color=direction),show.legend = F) +
  geom_hline(yintercept = -log10(0.05),linetype = "dotdash",color='green')+
  geom_vline(xintercept = c(-1,1),linetype = 'dotdash',color='green')+
  scale_color_manual(values = c('red','blue','grey')) +
  scale_fill_manual(values = c('red','blue','grey')) +
  scale_size(range = c(0.3,4)) + #规定了点的大小范围
  scale_x_continuous(breaks = seq(-5,5,1)) + 
  scale_y_continuous() + 
  labs(x = "log2(Fold Change)",y = "-log10(pvalue)",size = '|log2FoldChange|',color = 'difference express condition') +
  theme_dark()
  #这里将离散数值映射到图像属性

如果论文绘图,建议使用ggsci.ggiraph可以看作ggplot2的扩展包,有时间可以学.

相关推荐
weixin_466202782 小时前
第31周:天气识别(Tensorflow实战第三周)
分类·数据挖掘·tensorflow
山海青风5 小时前
使用 OpenAI 进行数据探索性分析(EDA)
信息可视化·数据挖掘·数据分析
莫叫石榴姐6 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
请你喝好果汁64110 小时前
单细胞|M3-4. 细胞聚类与轨迹推断
机器学习·数据挖掘·聚类
吾门11 小时前
YOLO入门教程(三)——训练自己YOLO11实例分割模型并预测【含教程源码+一键分类数据集 + 故障排查】
yolo·分类·数据挖掘
电子手信12 小时前
知识中台在多语言客户中的应用
大数据·人工智能·自然语言处理·数据挖掘·知识图谱
shansjqun12 小时前
教学内容全覆盖:航拍杂草检测与分类
人工智能·分类·数据挖掘
panpantt32114 小时前
【参会邀请】第二届大数据与数据挖掘国际会议(BDDM 2024)邀您相聚江城!
大数据·人工智能·数据挖掘
statistican_ABin14 小时前
R语言数据分析案例45-全国汽车销售数据分析(可视化与回归分析)
数据挖掘·数据分析
CV学术叫叫兽16 小时前
快速图像识别:落叶植物叶片分类
人工智能·分类·数据挖掘