动态统计图相比静态图更能够增加数据的展现力,有一种数据会说话的感觉。最近有人问动态条形图如何绘制?其实有很多途径都可以实现动态图的效果,比如gganimate包和ggplot2联合绘图;如果利用Rmd生成报告的话,利用code chunk选项也可以实现动态图的效果。
今天我们利用ggplot2和magick包生成gif图片的方式生成动态图。
比如,我们有一个具有两个变量的数据框,其中一个变量是year,存储年份值,另一个变量是num,存储的是登记处数量。我们现在想绘制一个条形图,X轴是年份,Y轴是登记处数量,以展现不同年份登记处数量变化情况。如果是静态图的话,不能体现登记处数量随着年份变化而变化的过程。那么,我们就让它动起来,让条图随着年份的变化逐渐出现。
大致绘图思路:
我们可以根据条形图中条的数量,绘制n个图,其中第1个图显示第1个年份的条,第2个图显示前2个年份的条,依次类推,最后1个图则显示所有条形,然后把这些图整合成为gif图片格式,实现动图效果。
数据准备方面,我们可以根据初始数据框生成n个数据框,其中,第1个数据框中num变量第1行为有效值,其余值为空;第2个数据框中num变量前2行为有效值,其余为空;依次类推。
R包准备方面,我们利用dplyr包整理数据,利用ggplot2绘图,利用magick包生成gif图片。
数据整理程序如下:
#加载dplyr包
library(dplyr)
##
## 载入程辑包:'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
#生成绘图所需的数据框
data <- data.frame(year=c(seq(1,9,1)),num=c(1,15,30,48,50,70,90,101,125))
#生成一个空的列表,用于存放生成的多个图
data1 <- list()
#利用for显示循环,生成n个图,并存放到data1列表中
for (i in 1:9){
data1[[i]]<- data%>%
mutate(num=ifelse(year<=i,num,NA),year=factor(year,labels = c("1959","2008","2012","2015","2017","2018","2019","2020","2021")))
}
绘图程序如下:
#加载ggplot2包
library(ggplot2)
#加载magick包
library(magick)
## Linking to ImageMagick 6.9.12.3
## Enabled features: cairo, freetype, fftw, ghostscript, heic, lcms, pango, raw, rsvg, webp
## Disabled features: fontconfig, x11
#利用magick打开一个图形设备,依据图形设备的参数生成图形。
fig <- image_graph(width=600,height = 400)
#在for循环中生成n个图形
for (i in 1:9){
p<-data1[[i]]%>%
ggplot(aes(x=year,y=num,fill=year))+
geom_bar(stat = "identity", show.legend = FALSE)+
scale_y_continuous(limits=c(0,130),breaks = seq(0, 130, by = 10),expand = c(0,0)) +
geom_text(aes(label=num),size=7)+
xlab("Year") + ylab("Number of Cancer Registries in Henan Province")+
theme_classic()+
theme(
axis.ticks = element_blank(),
axis.text = element_text(size=12),
axis.title = element_text(size=15),
)
print(p)
}
#关闭图形设备
dev.off()
## png
## 2
最后,利用magick包生成gif图片
#把图片向量的最后一张图放到最前面作为gif的封面图
fig<- c(fig[9],fig)
#生成gif图片,以每帧两秒的速度播放gif图片
image_animate(fig, fps = 2, dispose = "previous")
以上就是我们最终生成的动态条形图,在绘制图的过程中,需要注意的是,一定要保证所有过程图具有相同的横坐标和纵坐标刻度和范围,这样才能让图看起来只有条在动。