有人后台留言问我3Dbaplot 怎么画,刚好昨天有个群友也遇到这个问题。于是我在网上搜罗了一下。
哈神(Hadley Wickham)的ggplot2不支持画三维图形(3D plot)。有人在ggplot2的基础上进行开发,造出了一个
gg3D
包,可勉强实现三维坐标系的展示,但可操作性挺差,并没有流行起来。除了基于ggplot2的开发,
rgl
,
plot3D
,
scatterplot3d
和
plotly
(被称为有史以来最好的可视化工具,R和Python都有相应的扩展包)等这一系列包都支持3D画图。对于多数包,画三维点图(scatter plot)和密度图(density/surface plot)都比较容易实现,然而三维的柱状图(3D barchart)却不太容易实现。
偶然发现一个基于rgl包开发的包
barplot3d
大大方便了三维柱状图的画法。细查之后发现,该包的产生似乎有一段故事:
先附上作者名号:
Christopher Wardell
他其实先吐了一下饼图的槽,借用一个文章里的图:
Subclonal diversification of primary breast cancer revealed by multiregion sequencing by Yates et al, 2015
作者说这是150年前流行的图(不知他是说的是不是包括那个以
现代护理学之母
“提灯女神”南丁格尔的名字命名的
南丁格尔玫瑰图
)。
(内心OS:明明很酷的图好吧……)
作者也承认这种图很酷也漂亮,但它们是不合适的并且具有误导性的:
1.这些图看起来不合常理。读者花费了大量的精力来搞清楚他们在看什么,而不是处理数据中的关系。
2.这些数据只包含一个变量,但是上述图表可以表现两个变量(弧长和半径都可以变化)。因此,图表形式过于复杂。
3.在饼状图中,弧长与所表示的值成比例。在这些图中,每一块饼的弧长是相同的,但你可能意识不到,反而你可能会推断出某一段的弧长更少。这适用于弗洛伦斯•南丁格尔(Florence Nightingale)所绘制的数据类型(每年每个月的死亡人数),但不适用于任意划分。(哦,看来
南丁格尔玫瑰图
是
合理
的。)
4.在这些图中,每一段的半径(即它从中心延伸的距离)都能提供信息。你本应该读出一个几乎看不见的灰色虚线表示的同心圆刻度,但这并不容易。此外,该图视觉效果是非线性的,因为圆的面积是π·r ^ 2,这意味着半径上一个小的增加会产生一个不成比例的大变化。
5.很难在图之间进行比较。视觉比较非常困难,而通过阅读“Scale legend”来获得数字就更困难了。
为了原封不动保留作者的糟点,我基本是直译过来的。
只批评而不提供解决方案是没用的!!!
于是,作者有以下方案可供选择:
a, 柱状图(刚吐过柱状图的槽)。b, 箱线图。c, 3D柱状图
a,b 很boring但很实用,c实现起来略不容易。
这种类型的3D柱状图,首先是在Broad Institute的一篇关于测序文章中出现,继而流行开来。而且还有个不太学术的名字:乐高图(Lego plot)。
Exome and whole-genome sequencing of esophageal adenocarcinoma identifies recurrent driver events and mutational complexity by Dulak et al, 2013
对乐高图一番吹捧之后,能干的作者整出一个R包出来:
barplot3d
该包主要包含两个函数:
barplot3d()
和
legoplot3d()
下面我们来造数据试以下。
造数据:
1 set.seed(1234 )2 data 1:50 , 10 ),3 b = sample(1 :50 , 10 ),4 c = sample(1 :50 , 10 ),5 d = sample(1 :50 , 10 ))6 rownames(data) 1:10 ]
加载所需的包:
1 library (rgl)2 library (barplot3d)3 library (RColorBrewer)
我们加载了3个包。这三个包都可以通过
install.packages()
直接安装。rgl是barplot3d依赖的包,RColorBrewer是为了配色用的。
画图:
先用baseR画个水水的箱线图,仅一行代码(这个算是base包里
boxplot()
的优点吧):
1 boxplot(data, col = brewer.pal(4 ,"Dark2" ))
箱线图
三维柱状图(3Dbarplot):
1 barplot3d(rows = 10 , cols = 4 , 2 3 z = data %>% as.matrix(), 4 5 theta=30 , 6 7 phi=30 , 8 9 scalexy=20 ,10 11 sidecolors=brewer.pal(4 ,"Dark2" ), alpha=0.4 ,12 13 topcolors = brewer.pal(4 ,"Dark2" ),14 15 xlabels = colnames(data),16 17 ylabels = rownames(data),18 19 zlabels = TRUE )
出图如下:
3D barplot
这是个可以任意旋转的图,玩一玩~
转转看
再用barplot包里的测试数据画个“乐高图”:
1 x=system.file("extdata" , "signature_probabilities.txt" , package = "barplot3d" )2 sigdata=read.table(x,header=TRUE ,stringsAsFactors = FALSE )3 4 5 legoplot3d(contextdata=sigdata$Signature_8,6 labels=FALSE ,7 scalexy=0.01 ,8 sixcolors="sanger" ,9 alpha=0.4 )
lego plot