自從用了ggplot2包,越來越覺得其博大精深,通過圖層的概念可以繪製豐富的可視化圖形,如常見的散點圖、直方圖、條形圖、折線圖等。今天就教大家如何使用ggplot2實現地圖的繪製,以及如何在地圖中加入氣泡圖和條形圖。
本文所使用的數據來自於經管之家moonstone作者提供的流行病學樣本數據。有關地理信息數據可至文後的下載連結。
實操開始:
library(dplyr)
library(maptools)
library(ggplot2)
map_data <- readShapePoly(file.choose())
df_map <- map_data@data[,c('PINYIN_NAM', 'NAME')]
head(df_map)
df_map$id <- as.character(0:33)
head(df_map)
注意!這裡必須強調一點:不可以單獨將.shp文件放置在某個路徑下,還需同時將.dbf和.shx文件放到一起,否則會出現讀取數據失敗的問題。
可以通過fortify()函數將.shp文件中經緯度信息返回出來。
latitude_longitude <- fortify(map_data)
head(latitude_longitude)
下面將latitude_longitudd與df_map表進行關聯,目的是將經緯度信息對應到自個的省份中。
latitude_longitude <- latitude_longitude[, c('long', 'lat', 'id')] %>% left_join(., df_map, by = 'id')
head(latitude_longitude)
但數據集中並不是每個省只對應一個經緯度,而是各省輪廓的經緯度,下面需要為每個省創建一個經緯度,用以下文中的繪圖需要。
latitude_longitude <- tbl_df(latitude_longitude)
group_id <- group_by(.data = latitude_longitude, id)
center <- function(x) mean(range(x))
#聚合操作
province_location <- summarise(.data = group_id, latitude = center(lat), longitude = center(long))
#查看數據前6行
head(province_location)
doc_data <- read.csv(file = file.choose())
head(doc_data)
doc_data_select <- select(.data = doc_data, NAME1, Population, Dct_nur)
head(doc_data_select )
doc_data_select <- rename(.data = doc_data_select, NAME = NAME1)
head(doc_data_select)
下面將latitude_longitude表數據與doc_data_select表數據進行關聯,目的是將各省份的位置、名稱、人口和平均每千人醫護人員數鎖定到一起,用於下文的繪圖需要。
Province_Info <- province_location %>% left_join(., df_map, by = 'id') %>% left_join(., doc_data_select, by = 'NAME')
head(Province_Info)
將各省份詳細的輪廓經緯度數據與各省的醫療數據關聯。
latitude_longitude <- latitude_longitude %>% left_join(., Province_Info[, c('id','Population','Dct_nur')], by = 'id')
head(latitude_longitude)
目前所需數據均已準備好,包括各省中心點的經緯度、各省輪廓經緯度數據和各省流行病數據。下面就使用這些數據實現地圖的繪製。
#使用多邊形繪圖函數geom_polygon()繪製空的地圖
ggplot(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id)) + geom_polygon(colour = 'black', fill = 'white')
總覺得圖中坐標軸的存在很彆扭,該如何清除這些不必要的東西呢?
#清除不必要的附件(軸標籤、刻度標籤、刻度標記和網格線)
ggplot(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id)) + geom_polygon(colour = 'black', fill = 'white') + theme(axis.title = element_blank()) + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(panel.grid = element_blank())
theme(axis.title = element_blank())用於清除圖中的x軸和y軸標籤
theme(axis.text = element_blank())用於清除圖中x軸和y軸的刻度標籤
theme(axis.ticks = element_blank())用於清除圖中x軸和y軸的刻度標記
theme(panel.grid = element_blank())用於清除圖中的網格線
現在,我想將各個省份的名稱貼在地圖的各個省份中,該如何實現呢?
#將各省份的名稱顯示在地圖中,這裡多個主題函數theme()可以將參數寫到一起。
ggplot(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id)) + geom_polygon(colour = 'black', fill = 'white') + scale_fill_manual(values=colours(),guide=FALSE) + geom_text(mapping = aes(x = longitude, y = latitude, label = NAME), data = Province_Info, colour = 'steelblue') + theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), panel.grid = element_blank())
不錯,就是通過圖層疊加的方法,將對於位置的省份名稱貼在地圖中。這裡通過geom_text()函數實現,需要注意的是,geom_text()函數又使用了另一個數據框的數據內容。
現在,我又想通過顏色深淺來表示「平均每千人醫護人員數」的多少,該如何操作呢?
只需將欄位Dct_nur(「平均每千人醫護人員數」)映射給地圖的填充色即可。
ggplot(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id, fill = Dct_nur)) + geom_polygon(colour = 'black') + scale_fill_gradient(low = 'green', high = 'blue') + labs(title ="Numbers of doctor nand nurse per 1000 persons in China") + theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), panel.grid = element_blank())
發現圖中,臺灣地區的顏色為灰色,並不在對於的色階中,是因為醫療數據中沒有對應的臺灣數據。其實香港和澳門也沒響應的數據,這裡並沒法發現,是因為這兩個地區面積太小而無法識別出。
如果,我還想在地圖中再添加一個人口數量的維度,並使用氣泡圖的大小表示,該如何實現呢?
#在上一幅圖的基礎上,在繪製氣泡圖,氣泡大小表示人口數量
ggplot(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id, fill = Dct_nur)) + geom_polygon(colour = 'black') + geom_point(mapping = aes(x = longitude, y = latitude, size = Population), data = Province_Info, colour = 'red') + scale_fill_gradient(low = 'white', high = 'blue') + labs(title ="Numbers of doctor nand nurse per 1000 persons in China") + scale_size_area() + theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), panel.grid = element_blank())
這裡港澳臺地區的人口數位置,故沒有響應的氣泡。
除了可以在地圖裡添加氣泡圖,還可以往地圖裡添加條形圖,具體如下:
#實際上不是用geom_bar()函數往地圖裡添加條形圖,而是通過geom_errorbar()函數實現「條形圖」的,異曲同工,目的是在各省份中呈現條帶狀圖形。
ggplot() + geom_polygon(data = latitude_longitude, mapping = aes(x = long, y = lat, group = id, fill = Dct_nur), colour = 'black') + geom_errorbar(mapping = aes(x = longitude, ymin = latitude, ymax =latitude + Population*50), data = Province_Info, colour = 'brown', size = 3, width = 1, alpha = 0.8) + geom_text(mapping = aes(x = longitude, y = latitude, label = NAME), data = Province_Info, colour = 'black') + scale_fill_gradient(low = 'white', high = 'blue') + labs(title ="Numbers of doctor nand nurse per 1000 persons in China") + scale_size_area() + theme(axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), panel.grid = element_blank())
需要提醒的是,ggplot()函數裡不能傳任何參數,地圖只能在geom_polygon()函數中繪製,否則又將報錯。
由於省份中心位置不是很準確,導致有些省名稱、氣泡和條形圖沒有落在準確的位置,後期將對省份中心位置的經緯度做進一步調整。
劉順祥,天善智能社區專家。公眾號:每天進步一點點2015
Blog:https://ask.hellobi.com/blog/lsxxx2011
回復 R R語言快速入門免費視頻
回復 統計 統計方法及其在R中的實現
回復 用戶畫像 民生銀行客戶畫像搭建與應用
回復 大數據 大數據系列免費視頻教程
回復 可視化 利用R語言做數據可視化
回復 數據挖掘 數據挖掘算法原理解釋與應用
回復 機器學習 R&Python機器學習入門