交流群有一个昵称是“今西”的小伙伴说他做了一个常规的转录组分析,实验和对照两个组,各三个样本。他的老师希望能把一个基因集 里所有的基因(一个通路里面的,或者上下调最显著的基因列表)都做箱线图,表现在两个组中的表达情况。一个基因集中的基因往往超过十个,这次就不能像之前那样一个个的画图拼接,必须要用循环做图了。
但是循环的时候就报错了,他求助了他的师兄,发现问题就出在aes() 上,搜索到:
https:///questions/29425892/how-do-i-loop-through-column-names-and-make-a-ggplot-scatteplot-for-each-one 如下所示:
You need to explicitly print () the object returned by ggplot() in a for loop because auto-print()ing is turned off there (and a few other places). You also need to use aes_string() in place of aes() because you aren't using i as the actual variable in filter(提问者的dataframe) but as a character string containing the variable (in turn) in filter to be plotted.
让我们来演示一下“今西”小伙伴遇到的问题:
首先构造模拟数据df = as.data.frame(rbind(matrix(rnorm(260 ),nrow = 10 ), matrix(rexp(260 ),nrow = 10 ) )) colnames(df)=paste0('gene' ,LETTERS) condition = rep(c('case' ,'control' ),each=10 )library (ggplot2) gencounts = as.data.frame(cbind(condition,df)) gencounts[1 :4 ,1 :4 ]
如下所示:
> gencounts[1:4,1:4] condition geneA geneB geneC 1 case -1.1783525 0.5862758 0.8885539 2 case 0.5305503 -0.2297670 0.1225264 3 case -1.9248160 1.7752445 -0.6351263 4 case 2.8276993 0.5792767 -1.6000259
总共是26个基因,它们都是在case 和 control两个分组需要看表达量差异,而且case 和 control两个分组内部都是10个病人。
直接选取一个基因进行绘图# 任意一个基因绘图 ggplot(gencounts, aes (x=condition, y= geneY)) + geom_boxplot(width=0.3,aes(fill=factor(condition)),show.legend = FALSE) + theme_bw()
如下所示:
选取一个基因进行绘图 因为要写循环,对全部的基因批量绘图,所以“今西”小伙伴使用了如下所示的代码:
i =2 colnames(gencounts)[i]# 不报错,但是绘图是失败的后面的aes_string的差异 # 这里需要着重强调 aes 和 if (T){ ggplot(gencounts, aes (x=condition, y= colnames(gencounts)[i])) + geom_boxplot(width=0.3,aes(fill=factor(condition)),show.legend = FALSE) + theme_bw() }
然后就报错了,如果需要让上面的代码成功,需要做一个简单的修改, 就是ggplot的aes和aes_string的差异:
# 成功的绘图 ggplot(gencounts, aes_string (x='condition' , y= colnames(gencounts)[i])) + geom_boxplot(width=0.3,aes(fill=factor(condition)),show.legend = FALSE) + theme_bw()
测试后,就可以批量绘图并且拼接啦;
pl = lapply(2:ncol(gencounts), function (i){ ggplot(gencounts, aes_string (x='condition' , y= colnames(gencounts)[i])) + geom_boxplot(width=0.3,aes(fill=factor(condition)),show.legend = FALSE) + theme_bw() })#cowplot::plot_grid(plotlist = pl, align = "h", nrow = 4) patchwork::wrap_plots(pl,byrow = T, nrow =7)
如下所示:
批量绘图并且拼接 当然了,这个箱线图还可以进一步美化, 比如添加统计学检验指标:
# 箱线图可以更加自定义,比如添加统计学显著指标 i =2 colnames(gencounts)[i] ggplot(gencounts, aes_string (x='condition' , y= gencounts[,i]) ) + stat_boxplot(geom="errorbar" ,position=position_dodge(width=0.7 ),width=0.2 ,alpha=0.8 ,color="black" ) + geom_boxplot(width=0.3 ,aes(fill=factor(condition)),show.legend = FALSE ) + theme_bw()+ labs(y="Expression Level" ) + theme(panel.grid.major = element_blank(), #panel.grid.minor = element_blank(), panel.border = element_blank(), axis.line = element_line(colour = "black" ,size=1 ), axis.title.y=element_text(size=14 ),axis.text.y=element_text(size=14 ), axis.title.x=element_blank(),axis.text.x=element_text(size=14 ) ) + ggsignif::geom_signif(comparisons = list(c( 'case' ,'control' )), map_signif_level=T ,vjust=0.5 ,color="black" , textsize=5 ,test=t.test,step_increase=0.1 ) + scale_fill_manual(values=c("RoyalBlue" , "firebrick3" )) + ggtitle( colnames(gencounts)[i] )
如下所示:
添加统计学显著指标 该如何系统性学习ggplot呢如果你要从ggplot2开始一步步调制成为它这样的美图,需要下很深的功夫,一张统计图就是从数据到几何对象(点、线、条形等)的图形属性(颜色、形状、大小等)的一个映射。
✦ 数据(Data),最基础的是可视化的数据和一系列图形映射(aesthetic mappings),该映射描述了数据中的变量如何映射到可见的图形属性。 ✦ 几何对象(Geometric objects, geoms)代表在图中实际看到的点、线、多边形等。 ✦ 统计转换(Statistical trassformations, stats)是对数据进行某种汇总,例如将数据分组创建直方图,或将一个二维的关系用线性模型进行解释。 ✦ 标度(Scales)是将数据的取值映射到图形空间,例如用颜色、大小或形状来表示不同的取值,展现标度的常见做法是绘制图例和坐标轴。 ✦ 坐标系(Coordinate system, coord)描述数据是如何映射到图形所在的平面,同时提供看图所需的坐标轴和网格线。 ✦ 分面(faceting)如何将数据分解为子集,以及如何对子集作图并展示。 ✦ 主题(theme)控制细节显示,例如字体大小和图形的背景色。 前面我们介绍了绘图小白神包:
另外推荐5个ggplot2资源 ggplot2作者亲自写的书链接:https:///facet.html