用R语言画一个可以动的澳大利亚地理信息人数图
前几天有人找我画个图,他给我一些澳大利亚各个大洲的人数,对应每年变化的人数,这个人希望我可以做动起来,数据大概就是这样的:
图一
然后我做出来的结果是下面这样的:
图二
这个颜色对应的数据,(这样看其实不对,因为这个我做出来是动图,所以R都叠加出来了, 结果就是这样样子可以不断地动)
我写这个博客就是分享我是如何写出来的,已经思路,我也是菜鸟,所以一些都是弯路。大神莫怪。
第一步肯定是找到澳大利亚的地理信息数据
要画地图,必须搞到地图数据,这么偏的数据,怎么可能找到,第一步想到plotly包的地图数据,但是后来查了半天,也没找到,我看在StackOverflow上说,虽然plotly画美国地图很好,但是画澳大利亚别的国家,地图就会有锯齿,所以还是放弃了。
然后找ggmap,我心想这下肯定可以了,结果还是不行,因为ggmap要下载google地图,我在中国,怎么可能下载的了,(主要是不知道如何使用Google 开发者账号)。
然后找了很多,看来很多网站,才找到,R语言有两个包,一个是oz, 一个是ozmaps, 哈哈哈,终于找到了,但是找到了这两个包,我怎么知道如何提取数据呢??还有这些网页都写了详细的过程,然后我运行网站里面的代码,终于看懂了。
第一步安装包 加载包
install.packages(c("devtools", "dplyr", "oz", "ozmaps", "readxl"))
#下面通过library安装的包都要安装
devtools::install_github("thomasp85/transformr")
library(oz)
library(ozmaps)
library(ggplot2)
library(sf)
library(readxl)
library(dplyr)
library(gganimate)
library(tweenr)
加载地图数据
#地图数据
sf_oz <- ozmap_data("states")
上面加载完成后,你就可以在Rstudio变量窗口看到变量了,基本上结果如下图:
看右边的变量窗口,可以看到sf_oz数据,看左边窗口,可以看出来,sf_oz变量有两列,一列是NAME变量,一列是geometry 变量,我觉得这个意思就是:每一个名字对应一个地理位置数据。
看图一,图一的表的行名字就是各个州的名字,每一年对应的人数,就是要画出来的数据,这个图1的表的各个州名字和sf-oz变量名字要一一匹配,可以发现,客户给的数据没有sf-oz里面第九行(其他殖民地这个地区,所以,将这删掉。
sf_oz <- sf_oz[-9, ]
删掉之后,sf-oz数据如下:
图三
图一里面的名称都是中文,要翻译成英文然后一一对应,然后将这个客户给的数据和地理信息数据进行合并,得到如下结果:
data_state <- read_xlsx("中国留学生澳洲地区分布.xlsx")
names(data_state) <- c("year", (tibble::as_tibble(sf_oz))[, 1]$NAME)
data_state <- data_state[c(1:11), ]
value = as.matrix(data_state[, -1])
dim(value) <- 88
tidy_data <- tibble(value = value,
year = rep(data_state$year, time = 8),
NAME = rep(unlist(names(data_state)[-1]), each = 11)
)
test_data <- left_join(sf_oz, tidy_data, by = "NAME")
可以看出来,每一个地点,每一年,对应的人数对应的地理位置,都在一行中,这样的数据叫做长数据,我们上面代码的思路就是将客户给的宽数据转换成长数据,然后再将地理信息进行合并。就得到上面的结果了,如果不知道什么叫宽数据和长数据,可以看一下一个人写的[R语言宽数据和长数据如何转换]: https://www.sohu.com/a/110685641_464826: (我当时写的代码不行,太丑了,不知道如何转换宽长数据,导致写的代码很丑,当然现在会了)
上面就是数据处理结果,接下来就是画图:
画图部分
画图部分没有难点,主要就是注意如何将动图进行逐帧播放,如何设置,这个其实也简单,注意一些参数。然后要用到上面的gganimate包,为什么要加载tweenr包,我也不知道,因为如果不加载这个,好像运行有错误,。
anim <- ggplot(data = test_data) geom_sf(aes(fill = value))
theme(plot.title = element_text(hjust = 0.5))
scale_fill_continuous(low = "white", high = "darkblue")
transition_states(year) ggtitle("第{closest_state}年中国留澳学生分布")
animate(anim, 100, fps = 20, width = 1200, height = 1000,
renderer = gifski_renderer("australia.gif")) #改变第一100,可以改变帧数
上面代码就是将一个动态图画出来,怎么画的??我来一一解答:ggplot(data = test_data)
这个肯定知道,会用ggplot2
包画图的都知道要搞这个,毕竟是底层 geom_sf(aes(fill = value))
这你买了的geom_sf
是表示图层的基础不是普普通通的x,y坐标轴了,而是地理信息图层,这个geom_sf
函数是sf
包的函数,要注意啦,里面的aes(fill = value)
意思说,对不同的地区(区块)用test_data里面的value变量进行填充,这样就显而易见的将我们的人数填充到每个州了,ggtitle("第{closest_state}年中国留澳学生分布") theme(plot.title = element_text(hjust = 0.5))
这句话里面的ggtitle
是给图加个标题,theme(plot.title = element_text(hjust = 0.5))
是说让这个图的标题居中,theme
是对ggplot2
的一些个性化设置,plot.title
是意味着对标题进行设置,hjust
意味着对水平调整,0.5就是居中的意思,1就是右对齐,0就是左对齐。实际上如果test_data只是一年的数据就已经可以了,但是要动起来,必须加上transition_states(year)
这句话意思就是说,这个数据通过year这个变量来刷新,每一帧的变化,都是和时间有关。
有些人可能就疑惑了,如果我希望标题显示和年一起刷新,怎么办???,(就是当数据显示2017年的时候,标题就显示为“第2017年人数”,当数据刷新到2019年是,标题就是为“第2019年人数”)
实际上,这个gganimate作者就已经考虑到了,细心的朋友已经发现了,ggtitle
函数里面有个{closest_state}
,哈哈哈,这个就是不断地变化的东西,当你状态是2008, 这个{closest_state}
就显示2008, 你改成别的东西,还显示错误(这个我就当时改了,后来才知道,这个变量名字,不是随便改的)。
最后,就可以了。整个代码完成。
图也动起来了。