在之前的文章中,我们介绍了桑基图的可视化原理,而冲击图作为桑基图的一个子类,其展示的信息和桑基图基本一致,只不过在输入数据的格式上要略作调整。
绘制冲击图,推荐使用ggalluvial这个R包,从名字也可以看出,这个一个建立在ggplot2语法基础上的扩展包,官方链接如下
http://corybrunson.github.io/ggalluvial/articles/ggalluvial.html
首先通过一个冲击图的示例来了解下图中的基本元素
包括以下几种元素
1. axis, 即x轴代表的元素,在图中表现为每个竖直方向堆叠的柱状图,Gender, Dept
2. strata, 每个axis的分类标准,比如Gender的Strata 对应Male, Female
3. Freq, 即y轴代表的元素,对于每一个竖直方向的柱子,其各个子类Freq的总和是相同的
4. Admit, 即图例代表的元素,根据这个状态,把柱子间的连线,即代表数据流动的link分成了两类
要绘制这样的一幅图,首先来看下输入数据的格式
> library(ggalluvial)> data_wide <- as.data.frame(UCBAdmissions)
> head(data_wide)
Admit Gender Dept Freq
1 Admitted Male A 512
2 Rejected Male A 313
3 Admitted Female A 89
4 Rejected Female A 19
5 Admitted Male B 353
6 Rejected Male B 207
这样的数据格式为称之为宽格式,可以看到x轴的数据,对应的是数据框中的列,先用默认参数看下效果,代码如下
> ggplot(data_wide, aes(y = Freq, axis1 = Gender, axis2 = Dept)) ++ geom_alluvium() +
+ geom_stratum() +
+ geom_label(stat = "stratum", aes(label = after_stat(stratum)))
效果图如下
为了达到示例图中的效果,我们需要做一下调整
1. 把柱子的填充色设置为黑色
2. 把柱子的宽度变窄
3. 把连线按照Admit属性赋予不同颜色
4. 添加x轴标签
代码如下
> ggplot(data_wide, aes(y = Freq, axis1 = Gender, axis2 = Dept)) ++ geom_alluvium(aes(fill = Admit), width = 1/4) +
+ geom_stratum(fill = "black", colour = "white", width = 1/4) +
+ geom_label(stat = "stratum", aes(label = after_stat(stratum))) +
+ scale_x_continuous(breaks = 1:2, labels = c("Gender", "Dept"))
效果图如下
宽格式的数据适合柱子较少的情况,我们可以依次在代码中指定需要绘制的列,但是当柱子较多时,使用这种宽格式就比较费时了,此时,就可以使用长格式的输入文件,示例如
> head(data_long)
Admit Freq num x stratum
1 Admitted 512 1 Gender Male
2 Rejected 313 2 Gender Male
3 Admitted 89 3 Gender Female
4 Rejected 19 4 Gender Female
5 Admitted 353 5 Gender Male
6 Rejected 207 6 Gender Male
> ggplot(data_long,
+ aes(x = x, y = Freq, fill = Admit, stratum = stratum, alluvium = num)) +
+ geom_flow() +
+ geom_stratum(fill = "black", colour = "white") +
+ geom_label(stat = "stratum", aes(label = after_stat(stratum)), fill = "white")
效果图如下
宽数据比较符合我们的常规直觉,而长数据则是ggplot2绘图语法的直接适配者,核心还是那句话,任意一个图中的元素都对应数据框中的某一列。
通过长数据,我们可以更好的控制图形中各种属性的映射,比如官方自带的一个示例
> ggplot(vaccinations,+ aes(x = survey, stratum = response, alluvium = subject,
+ y = freq,
+ fill = response, label = response)) +
+ scale_x_discrete(expand = c(.1, .1)) +
+ geom_flow() +
+ geom_stratum(alpha = .5) +
+ geom_text(stat = "stratum", size = 3) +
+ theme(legend.position = "none") +
+ ggtitle("vaccination survey responses at three points in time")
效果图如下
轻松实现用柱子中分类变量的属性来映射连线的颜色,使得图片更加的美观。
·end·