用R畫地圖數據
首先,從這里下載中國地圖的GIS數據,這是一個壓縮包,完全解壓后包含三個文件(bou2_4p.dbf、bou2_4p.shp和bou2_4p.shx),將這三個文件解壓到同一個目錄下。
用R繪制地圖比較簡單。比如畫一下全國范圍的區域,可以用如下代碼:
library(maptools) mydat = readShapePoly("china-province-border-data.tar/china/bou2_4p.shp") #地圖包位置,根據自己的角標位置設置 plot(mydat)
生成的圖如下:
但是,可以看出這樣繪制的地圖的形狀有些扁平。這是因為,在繪圖的過程中,默認把經度和緯度作為普通數據,均勻平等對待,繪制在笛卡爾坐標系上造成的。其實,地球的球面圖形如何映射到平面圖上,在地理學上是有一系列不同的專業算法的。地圖不應該畫在普通的笛卡爾坐標系上,而是要畫在地理學專業的坐標系上。
也可以安裝maps
和mapdata
這兩個包,然后輸入下面的命令:
install.packages(mapdata) install.packages("mapdata") library(maps) library(mapdata) map("china")
生成的圖如下:
其中map()
函數還可以加上很多參數,大致如下:
map(database = "world", regions = ".", exact = FALSE, boundary = TRUE, interior = TRUE, projection = "", parameters = NULL, orientation = NULL, fill = FALSE, col = 1, plot = TRUE, add = FALSE, namesonly = FALSE, xlim = NULL, ylim = NULL, wrap = FALSE, resolution = if (plot) 1 else 0, type = "l", bg = par("bg"), mar = c(4.1, 4.1, par("mar")[3], 0.1), myborder = 0.01, ...)
可以設置數據庫、地區、精確度、邊界等,在這里就不一一詳述,具體的用法可以?map。
給地圖上色
在實際使用的過程中,我們往往會根據自己的需要對地圖中的某些省份著以特定的顏色,這時就可以通過調節plot
命令中的fg
參數來予以實現。
首先看看R繪制地圖的原理:
在繪制地圖時,每一個省市自治區或者島嶼都是用一個多邊形來表示的。之前的GIS數據,其實就是提供了每一個行政區其多邊形逐點的坐標,然后R軟件通過順次連接這些坐標,就繪制出了一個多邊形區域。在上面的數據中,一共包含了925個多邊形的信息,之所以有這么多是因為一些省份有很多小的附屬島嶼。在這925個多邊形中,每一個都對應一個唯一的ID,編號分別從1到925。
plot
命令中的fg
參數在本例中應該是一個長度為925的向量,其第i個分量的取值就代表了地圖中第i個多邊形的顏色。一個簡單的嘗試是運行下面這個命令看看效果:
plot(x,col=gray(924:0/924));
生成的圖如下所示:
于是自然就產生了一個問題:如何獲取某一個特定地區的ID,進而設置我們想要的顏色?事實上,在變量x中,就已經存儲了我們想要的信息。在R中輸入“x[[2]]
”或“x$att.data
”,會得到一個925行7列的數據框,這其實是bou2_4p.dbf這個文件中存儲的信息,之前的read.shape()
函數雖然讀取的是bou2_4p.shp文件,但在默認情況下會把dbf文件的信息也放到變量之中。對于這個數據框,其行名就是每一個區域的ID編號,第一列和第二列分別是面積和周長,最后一列是該區域所屬的行政區名,其它的列應該也是一些編號性質的變量。于是,通過查找相應的行政區對應的行名,就可以對fg
參數進行賦值了。下面是我編的一個函數,用來生成所需的col向量:
getColor=function(mapdata,provname,provcol,othercol) { f=function(x,y) ifelse(x %in% y,which(y==x),0); colIndex=sapply(mapdata@data$NAME,f,provname); col=c(othercol,provcol)[colIndex+1]; return(col); }
其中mapdata
是存放地圖數據的變量,在上面的例子中就是x,provname
是需要改變顏色的地區的名稱,provcol
是對應于provname
的代表顏色的向量(名稱和數字均可),othercol
是其它地區的顏色。舉例如下:
provname=c("北京市","天津市","上海市","重慶市"); provcol=c("red","green","yellow","purple"); plot(x,col=getColor(x,provname,provcol,"white"));
生成的圖數據如下:
生成人口數據分布圖
利用類似的方法就可以根據自己的需要對不同的區域進行著色,下面再舉一例。從國家統計局獲取2007年我國各地區的人口數據,然后根據人口的多少對各省份進行著色。程序如下:
provname=c("北京市","天津市","河北省","山西省","內蒙古自治區", "遼寧省","吉林省","黑龍江省","上海市","江蘇省", "浙江省","安徽省","福建省","江西省","山東省", "河南省","湖北省","湖南省","廣東省", "廣西壯族自治區","海南省","重慶市","四川省","貴州省", "云南省","西藏自治區","陜西省","甘肅省","青海省", "寧夏回族自治區","新疆維吾爾自治區","臺灣省", "香港特別行政區"); pop=c(1633,1115,6943,3393,2405,4298,2730,3824,1858,7625, 5060,6118,3581,4368,9367,9360,5699,6355,9449, 4768,845,2816,8127,3762,4514,284,3748,2617, 552,610,2095,2296,693); provcol=rgb(red=1-pop/max(pop)/2,green=1-pop/max(pop)/2,blue=0); plot(x,col=getColor(x,provname,provcol,"white"),xlab="",ylab="");
生成的圖如下:
其中顏色越深的地方代表人口數越多,反之為人口數越少。
畫部分省地圖
在繪制地圖的過程中,還有一個比較有用的參數是recs
,它是一個由多邊形ID組成的向量,表示在地圖中只畫出這些ID所代表的區域。利用這個參數,就可以畫出某一部分的地圖,例如下面的例子是我國中部六省的地圖:
getID=function(mapdata,provname) { index=mapdata$att.data$NAME %in% provname; ids=rownames(mapdata$att.data[index,]); return(as.numeric(ids)); } midchina=c("河南省","山西省","湖北省","安徽省","湖南省","江西省"); plot(x, col = getColor(x, midchina, rep("green", 6), "white"), border = "white", xlab = "", ylab = "")
生成的圖:
用R畫中國地圖并標注城市位置
畫出的圖上仍然可以用points()
函數和text()
函數加上點和文字,而maptools
包中還提供了一個pointLabel()
函數,用來解決文本標簽的重疊問題。
par(mar=rep(0,4)) dat = read.csv(text = "城市,jd,wd 北 京,116.4666667,39.9 上 海,121.4833333,31.23333333 天 津,117.1833333,39.15 重 慶,106.5333333,29.53333333 哈爾濱,126.6833333,45.75 長 春,125.3166667,43.86666667 沈 陽,123.4,41.83333333 呼和浩特,111.8,40.81666667 石家莊,114.4666667,38.03333333 太 原,112.5666667,37.86666667 濟 南,117,36.63333333 鄭 州,113.7,34.8 西 安,108.9,34.26666667 蘭 州,103.8166667,36.05 銀 川,106.2666667,38.33333333 西 寧,101.75,36.63333333 烏魯木齊,87.6,43.8 合 肥,117.3,31.85 南 京,118.8333333,32.03333333 杭 州,120.15,30.23333333 長 沙,113,28.18333333 南 昌,115.8666667,28.68333333 武 漢,114.35,30.61666667 成 都,104.0833333,30.65 貴 陽,106.7,26.58333333 福 州,119.3,26.08333333 臺 北,121.5166667,25.05 廣 州,113.25,23.13333333 海 口,110.3333333,20.03333333 南 寧,108.3333333,22.8 昆 明,102.6833333,25 拉 薩,91.16666667,29.66666667 香 港,114.1666667,22.3 澳門,113.5,22.2") library(maps) library(mapdata) map("china", col = "darkgray", ylim = c(18, 54), panel.first = grid()) points(dat$jd, dat$wd, pch = 19, col = rgb(0, 0, 0, 0.5)) text(dat$jd, dat$wd, dat[, 1], cex = 0.9, col = rgb(0, 0, 0, 0.7), pos = c(2, 4, 4, 4, 3, 4, 2, 3, 4, 2, 4, 2, 2, 4, 3, 2, 1, 3, 1, 1, 2, 3, 2, 2, 1, 2, 4, 3, 1, 2, 2, 4, 4, 2)) axis(1, lwd = 0); axis(2, lwd = 0); axis(3, lwd = 0); axis(4, lwd = 0)
生成的圖:
ggplot2繪制地圖
以中國地圖為例,下載最新的ArcGIS矢量地圖數據,這種地圖數據包含了很多信息,這是畫地圖的基礎數據。下載地址:
http://download.csdn.net/detail/lgstarzkhl/9427677
用以下代碼進行地圖繪制:
library(maptools) library(ggplot2) library(plyr) #讀取地圖文件 china_map<-readShapePoly("C:/Users/feng/Desktop/chinaprovinceborderdata_tar_gz/china-province-border-data.tar/Lambert/省級行政區.shp") #提取用于繪圖的地圖數據 x<-china_map@data xs<-data.frame(x,id.1=seq(0:33)-1) #將地圖數據轉換為數據框 china_map1<-fortify(china_map) #添加一個id.1字段,用于和上面的xs(各省市數據)糅合,合并 china_map1$id.1<-china_map1$id #去掉china_map1中的id字段,避免在糅合數據的時候,出現兩個相同字段id和id.1,保證只用id.1來糅合 china_map2<-china_map1[,-7] #糅合地圖數據 china_mapdata<-join(china_map2, xs, type = "full") #繪制地圖 ggplot(china_mapdata, aes(x = long, y = lat, group = group,fill=NAME))+ geom_polygon( )+ geom_path(colour = "grey40")+ scale_fill_manual(values=colours(),guide=FALSE)
生成的圖:
總結
使用R的地圖擴展包可以畫出各種樣式的地圖,具體的展現形態及結合方式還有待進一步挖掘。
文章列表