交流群有一個昵稱是“今西”的小伙伴說他做了一個常規的轉錄組分析,實驗和對照兩個組,各三個樣本。他的老師希望能把一個基因集 里所有的基因(一個通路里面的,或者上下調最顯著的基因列表)都做箱線圖,表現在兩個組中的表達情況。一個基因集中的基因往往超過十個,這次就不能像之前那樣一個個的畫圖拼接,必須要用循環做圖了。
但是循環的時候就報錯了,他求助了他的師兄,發現問題就出在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