0%

绘制桑基图

本文介绍用以下包绘制桑基图。

  • ggalluvial包
  • sankeyD3包

1. ggalluvial包绘制桑基图

1.1 长数据绘制

数据准备:

1
2
3
4
5
6
7
8
9
10
11
12
> head(my_data)
# A tibble: 6 x 7
Freq group stage m6A x y id
<int> <chr> <chr> <fct> <fct> <fct> <int>
1 404 m6A+m6A-m6A-m6A- Stage1 m6A+ Stage1 m6A+ 2
2 404 m6A+m6A-m6A-m6A- Stage2 m6A- Stage2 m6A- 2
3 404 m6A+m6A-m6A-m6A- Stage3 m6A- Stage3 m6A- 2
4 404 m6A+m6A-m6A-m6A- Stage4 m6A- Stage4 m6A- 2
5 363 m6A-m6A+m6A-m6A- Stage1 m6A- Stage1 m6A- 3
6 363 m6A-m6A+m6A-m6A- Stage2 m6A+ Stage2 m6A+ 3
7 363 m6A-m6A+m6A-m6A- Stage3 m6A- Stage3 m6A- 3
8 363 m6A-m6A+m6A-m6A- Stage4 m6A- Stage4 m6A- 3

绘图所需要的数据,如上所示,这个方法绘图,数据需要是tidy的,即用长数据作图。
绘图代码:

1
2
3
4
5
6
7
8
9
10
11
p1 <- ggplot(my_data,
aes(x = x, stratum = m6A, alluvium = id,
y = Freq,
fill = m6A, label = m6A)) +
scale_x_discrete(expand = c(.1, .1)) +
geom_flow() +
geom_stratum(alpha = .5) +
geom_text(stat = "stratum", size = 3) +
theme(legend.position = "none") +
theme_classic()
p1

结果如图:
alt 图标

绘图语法与ggplot2一致,函数包含以下变量:

  • 首先确定图的axis,x轴表示不同时期,沿着x轴表示不同位置的水平分组;
  • 每个轴上的分组被描绘成不透明的块,称为地层(strata)。Stage1轴包含m6A+和m6A-;
  • 被称为**冲积(alluvia)**的水平(x-)样条横跨地块的宽度。在这个图中,每个冲积层对应于每个轴变量的固定值,由其在轴上的垂直位置表示,以及由其填充颜色表示的Survived变量的固定值。
  • 在相邻轴线之间的冲积层片段是水流(flow)。
    冲积层在矿脉处(lodes)与地层相交。上述图中没有显示矿脉,但可以推断为填充的矩形,这些矩形在图的每一端延伸流过地层的流动,或连接中心地层两侧的流动。

具体到本例,即:

  • axis:x轴为不同stage、x轴不同取值的组合代表不同分组,y轴由每个轴变量的值表示,即每个分组的flow宽度,即Freq;
  • stratum:为x轴每个分块的取值;
  • alluvium:为每个分组的id,用以区分不同的组;

但是这样画出的图,不详细区分每个组分,在stage2出来之后,就不会记得stage1的状态。如果要区分每一个group的话,需要在geom_flow()中加stat = "alluvium"参数,配合lode.guidance = "frontback"参数一起,效果更好,color指定边界的颜色:

1
2
3
4
5
6
7
8
9
10
11
p2 <- ggplot(my_data,
aes(x = x, stratum = m6A, alluvium = id,
y = Freq,
fill = m6A, label = m6A,alpha=0.5)) +
geom_flow(stat = "alluvium", lode.guidance = "frontback",
color = "darkgray") +
geom_stratum() +
geom_text(stat = "stratum", size = 3,color="black") +
theme(legend.position = "bottom") +
theme_classic()
p2

alt 图标

1.2 宽数据绘制

1
2
3
4
5
6
7
8
head(my_df)
MII L1C L2C 4C Freq group
1 m6A- m6A- m6A- m6A- 4329 m6A-m6A-m6A-m6A-
2 m6A+ m6A- m6A- m6A- 404 m6A+m6A-m6A-m6A-
3 m6A- m6A+ m6A- m6A- 363 m6A-m6A+m6A-m6A-
4 m6A+ m6A+ m6A- m6A- 558 m6A+m6A+m6A-m6A-
5 m6A- m6A- m6A+ m6A- 523 m6A-m6A-m6A+m6A-
6 m6A+ m6A- m6A+ m6A- 174 m6A+m6A-m6A+m6A-

宽数据绘制:

1
2
3
4
5
6
7
8
9
ggplot(my_df,
aes(y = Freq,
#fill=group,
axis1 = MII, axis2 = L1C, axis3 = L2C,axis4 = `4C`)) +
geom_flow(stat = "alluvium", lode.guidance = "frontback") +
scale_x_discrete(limits = c("MII", "L1C", "L2C","4C")) +
geom_stratum() +
geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
theme_bw()

如图所示:
alt 图标

2. sankeyD3包绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
install.packages("devtools")
devtools::install_github("fbreitwieser/sankeyD3")
library(sankeyD3)

links<-data.frame(source=c("脐橙","苹果","脐橙","梨","香蕉","北京","北京","南京","上海","南京"),
target=c("北京","北京","南京","上海","南京","AAA","BBB","AAA","BBB","CCC"),
weight=c(30,56,39,56,33,30,56,39,56,33))
nodes <- data.frame(name=c(as.character(links$source), as.character(links$target)) %>% unique())
links$IDsource <- match(links$source, nodes$name)-1;
links$IDtarget <- match(links$target, nodes$name)-1;

nodes$color<-sample(c("red","orange","blue","green"),nrow(nodes),replace=T)

links$group<-rep("A",nrow(links))
links$group[links$weigth<50 & links$weigth>=35]<-"B"
links$group[links$weigth<35]<-"C"

sankeyNetwork(Links = links, Nodes = nodes,
Source = "IDsource", Target = "IDtarget",
Value = "weight", NodeID = "name",
nodeWidth =10,units = 'TWh',
numberFormat=".0f",fontSize = 8,
NodeColor="color",LinkGroup="group")

alt 图标