情况提要
2019年1月7日中午接到TeamLeader钟的电话,果然有大事发生 我们的建模论文有点点小问题,地图要重新画 本来以为可以ps截图解决,但TeamLeader要求比较高,只好重画 GEODA我又没用过,于是,捡起几年前的R画地图的东西,7点开工 好在TeamLeader非常能干找到了底图,于事加班到11点半,完成
需要的基础数据
要画地图,毫无疑问,首先需要的是底图, 因为我们需要着色,必须是多边形地图,一般文件名为bou2_4p.shp 全名的话,就是boundary_polygon_polygon.shp,当然还有几个配套的文件
另外需要的就是自已的数据文件,根据数据中的变量来叠加颜色、标注等内容
主要过程
- 把shp底图中的数据分解成数据框
- 找到底图数据框与自已数据的对应关系
- 将两者合并
- 画图,调整样式,保存
正式开始啦
- 载入3个包,maptools处理地图,tidyverse整理数据,stringr处理文字
library(maptools)
library(tidyverse)
library(stringi)
1.1 读入底图数据
citysmap <- readShapePoly("e:/gitR/map/zhong17/state/STATE_poly.shp")
1.2 读入要用到的数据
cdata <- read_csv('cdata.csv', locale = locale(encoding='GB18030'))
1.3 初始化用的基础数据
stdnames <- c("高水平", "较高水平", "中等水平", "较低水平", "低水平", '无数据')
std <- c(1.5,0.8,0.5,0.3,0)
cb_palette <- c('1'="#D32F2F", '2'="#CC79A7", '3'="#43A047", '4'="#76D7C4", '5'="#0072B2", '9'="#CFD8DC")
years=c(2009, 2012, 2014, 2016)
2.1 赋发展程度的函数
ranklevel <- function(value){
return(min(which((c(1.5,0.8,0.5,0.3,0)-value)<=0)))
}
2.2 数据简单处理, 提取需要变量,赋发展程度,并检验
csdata <- select(cdata, CITYCN, CITYEN, datayear, cityrank)
csdata$level <- as.factor( sapply(csdata$cityrank, ranklevel))
table(csdata$level)
1 2 3 4 5
36 178 453 1049 244
3.1 把底图数据用fortify函数提取数据框, 提取后数据结构如下
mapnp <- fortify(citysmap)
Regions defined for each Polygons
head(mapnp)
提取数据框后的底图,只有经纬度数据和分组数据, 标明地域的只有id,但id只是没有实际意义的序列
3.2 所以必须取出底图的地域信息
mdata <- citysmap@data
head(mdata)
可以发现,这个基本信息比较全,有地区的中文名称,行政中心位置面积等 另外可以发现,底图数据框的id就是这个信息数据框的行号 这样,经过简单处理,两部分数据就可以拼合了 不过,鉴于底图数据框行数很大,有523987行, 最好一次只拼合一年的数据,以免内存溢出
mdata <- mutate(mdata, id=rownames(mdata), CITYCN=as.character(NAME99))
4.1 拼合数据并画图, 用中文名称将自有数据与底图信息数据拼合, 用id将底图信息与底图数据框拼合, 这样就能用ggplot2画图了 调整好配色,数据标签位置,标图完整后就可以保存了
plotyear <- function(year){
mdata.y <- left_join(mdata, filter(csdata, datayear==year), by='CITYCN')
mapnp.y <- left_join(mapnp, mdata.y, by='id')
pm <- ggplot(data = mapnp.y)
pm <- pm + geom_polygon(aes(x = long, y = lat, fill=level, group = group), color = "black")
pm <- pm + labs( x = "经度", y = "纬度",title =paste(year,'年'))
pm <- pm + theme(legend.position=c(0.1,0.15))
pm <- pm + scale_fill_manual(values=cb_palette, name = "高质量发展水平", labels = stdnames)
print(pm)
ggsave(paste(year, '.png'), pm, width = 10, height = 8, dpi = 150)
}
5.1 循环执行需要作图的年份,即可得到多年的图了
for(year in years) plotyear(year)




后记
TeamLeader的标准果然不同凡响,所以她是TeamLeader, 8号一早,我又画了2个小时将图P成可以用的样子
地图杂谈
其实我们画中国的图要烦死了,因为R并没有自带中国内部的底图, 如果要画美国的地图简单死了,因为已有R包内置了美国的底图, 比如画个美国各州的地图,只要读入相应数据画下就OK 此部分参考自Eric C. Anderson 的 Making Maps with Rhttp://eriqande.github.io/rep-res-web/lectures/making-maps-with-R.html
states <- map_data("state")
Attaching package: 愼㸱愼㹥maps愼㸱愼㹦
The following object is masked from 愼㸱愼㹥package:purrr愼㸱愼㹦:
map
ggplot(data = states) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group), color = "white")+
guides(fill=FALSE)

而且,更加变态的是,美国的地图数据可以分县(ps,美国没有地级行政区划), 演示一个,把加州各县的图画一下,就是这么easy
counties <- map_data("county")
ca_county <- subset(counties, region == "california")
ggplot(data = ca_county) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group), color = "white")+
guides(fill=FALSE)

但是,很抱歉,如果想读中国的是没有的,如下:
china <- map_data("china")
Error: 'chinaMapEnv' is not an exported object from 'namespace:maps'
不过用这个数据还可以画世界地图倒是没问题
world <- map_data("world")
ggplot(data = world) +
geom_polygon(aes(x = long, y = lat, fill = region, group = group), color = "white")+
guides(fill=FALSE)

现在是Wed Jan 09 13:10:10 2019,该就寝了,bye my305
LS0tDQp0aXRsZTogIueUu+WcsOWbvueahE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIOaDheWGteaPkOimgQ0KDQoyMDE55bm0MeaciDfml6XkuK3ljYjmjqXliLBUZWFtTGVhZGVy6ZKf55qE55S16K+d77yM5p6c54S25pyJ5aSn5LqL5Y+R55SfDQrmiJHku6znmoTlu7rmqKHorrrmlofmnInngrnngrnlsI/pl67popjvvIzlnLDlm77opoHph43mlrDnlLsNCuacrOadpeS7peS4uuWPr+S7pXBz5oiq5Zu+6Kej5Yaz77yM5L2GVGVhbUxlYWRlcuimgeaxguavlOi+g+mrmO+8jOWPquWlvemHjeeUuw0KR0VPREHmiJHlj4jmsqHnlKjov4fvvIzkuo7mmK/vvIzmjaHotbflh6DlubTliY3nmoRS55S75Zyw5Zu+55qE5Lic6KW/77yMN+eCueW8gOW3pQ0K5aW95ZyoVGVhbUxlYWRlcumdnuW4uOiDveW5suaJvuWIsOS6huW6leWbvu+8jOS6juS6i+WKoOePreWIsDEx54K55Y2K77yM5a6M5oiQDQoNCiMjIyDpnIDopoHnmoTln7rnoYDmlbDmja4NCuimgeeUu+WcsOWbvu+8jOavq+aXoOeWkemXru+8jOmmluWFiOmcgOimgeeahOaYryoq5bqV5Zu+KirvvIwNCuWboOS4uuaIkeS7rOmcgOimgeedgOiJsu+8jOW/hemhu+aYr+Wkmui+ueW9ouWcsOWbvu+8jOS4gOiIrOaWh+S7tuWQjeS4umBib3UyXzRwLnNocGANCuWFqOWQjeeahOivne+8jOWwseaYr2Bib3VuZGFyeV9wb2x5Z29uX3BvbHlnb24uc2hwYO+8jOW9k+eEtui/mOacieWHoOS4qumFjeWll+eahOaWh+S7tg0KDQrlj6blpJbpnIDopoHnmoTlsLHmmK8qKuiHquW3sueahOaVsOaNruaWh+S7tioq77yM5qC55o2u5pWw5o2u5Lit55qE5Y+Y6YeP5p2l5Y+g5Yqg6aKc6Imy44CB5qCH5rOo562J5YaF5a65DQoNCiMjIyDkuLvopoHov4fnqIsNCjEuIOaKinNocOW6leWbvuS4reeahOaVsOaNruWIhuino+aIkOaVsOaNruahhg0KMi4g5om+5Yiw5bqV5Zu+5pWw5o2u5qGG5LiO6Ieq5bey5pWw5o2u55qE5a+55bqU5YWz57O7DQozLiDlsIbkuKTogIXlkIjlubYNCjQuIOeUu+Wbvu+8jOiwg+aVtOagt+W8j++8jOS/neWtmA0KDQojIyDmraPlvI/lvIDlp4vllaYNCjAuIOi9veWFpTPkuKrljIXvvIxtYXB0b29sc+WkhOeQhuWcsOWbvu+8jHRpZHl2ZXJzZeaVtOeQhuaVsOaNru+8jHN0cmluZ3LlpITnkIbmloflrZcNCmBgYHtyfQ0KbGlicmFyeShtYXB0b29scykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzdHJpbmdpKQ0KYGBgDQoNCg0KMS4xIOivu+WFpeW6leWbvuaVsOaNrg0KYGBge3J9DQpjaXR5c21hcCA8LSByZWFkU2hhcGVQb2x5KCJlOi9naXRSL21hcC96aG9uZzE3L3N0YXRlL1NUQVRFX3BvbHkuc2hwIikNCmBgYA0KDQoNCjEuMiDor7vlhaXopoHnlKjliLDnmoTmlbDmja4NCmBgYHtyfQ0KY2RhdGEgPC0gcmVhZF9jc3YoJ2NkYXRhLmNzdicsIGxvY2FsZSA9IGxvY2FsZShlbmNvZGluZz0nR0IxODAzMCcpKQ0KYGBgDQoNCjEuMyDliJ3lp4vljJbnlKjnmoTln7rnoYDmlbDmja4NCmBgYHtyfQ0Kc3RkbmFtZXMgPC0gYygi6auY5rC05bmzIiwgIui+g+mrmOawtOW5syIsICLkuK3nrYnmsLTlubMiLCAi6L6D5L2O5rC05bmzIiwgIuS9juawtOW5syIsICfml6DmlbDmja4nKQ0Kc3RkIDwtIGMoMS41LDAuOCwwLjUsMC4zLDApDQpjYl9wYWxldHRlIDwtIGMoJzEnPSIjRDMyRjJGIiwgJzInPSIjQ0M3OUE3IiwgJzMnPSIjNDNBMDQ3IiwgJzQnPSIjNzZEN0M0IiwgJzUnPSIjMDA3MkIyIiwgJzknPSIjQ0ZEOERDIikNCnllYXJzPWMoMjAwOSwgMjAxMiwgMjAxNCwgMjAxNikNCmBgYA0KDQoyLjEg6LWL5Y+R5bGV56iL5bqm55qE5Ye95pWwDQpgYGB7cn0NCnJhbmtsZXZlbCA8LSBmdW5jdGlvbih2YWx1ZSl7DQogIHJldHVybihtaW4od2hpY2goKGMoMS41LDAuOCwwLjUsMC4zLDApLXZhbHVlKTw9MCkpKQ0KfQ0KYGBgDQoNCg0KMi4yIOaVsOaNrueugOWNleWkhOeQhu+8jA0K5o+Q5Y+W6ZyA6KaB5Y+Y6YeP77yM6LWL5Y+R5bGV56iL5bqm77yM5bm25qOA6aqMDQpgYGB7cn0NCmNzZGF0YSA8LSBzZWxlY3QoY2RhdGEsIENJVFlDTiwgQ0lUWUVOLCBkYXRheWVhciwgY2l0eXJhbmspDQpjc2RhdGEkbGV2ZWwgPC0gYXMuZmFjdG9yKCBzYXBwbHkoY3NkYXRhJGNpdHlyYW5rLCByYW5rbGV2ZWwpKQ0KdGFibGUoY3NkYXRhJGxldmVsKQ0KYGBgDQoNCjMuMSDmiorlupXlm77mlbDmja7nlKhgZm9ydGlmeWDlh73mlbDmj5Dlj5bmlbDmja7moYbvvIwNCuaPkOWPluWQjuaVsOaNrue7k+aehOWmguS4iw0KYGBge3J9DQptYXBucCA8LSBmb3J0aWZ5KGNpdHlzbWFwKQ0KaGVhZChtYXBucCkNCmBgYA0K5o+Q5Y+W5pWw5o2u5qGG5ZCO55qE5bqV5Zu+77yM5Y+q5pyJ57uP57qs5bqm5pWw5o2u5ZKM5YiG57uE5pWw5o2u77yMDQrmoIfmmI7lnLDln5/nmoTlj6rmnIlpZO+8jOS9hmlk5Y+q5piv5rKh5pyJ5a6e6ZmF5oSP5LmJ55qE5bqP5YiXDQoNCg0KMy4yIOaJgOS7peW/hemhu+WPluWHuuW6leWbvueahOWcsOWfn+S/oeaBrw0KYGBge3J9DQptZGF0YSA8LSBjaXR5c21hcEBkYXRhDQpoZWFkKG1kYXRhKQ0KYGBgDQrlj6/ku6Xlj5HnjrDvvIzov5nkuKrln7rmnKzkv6Hmga/mr5TovoPlhajvvIzmnInlnLDljLrnmoTkuK3mloflkI3np7DvvIzooYzmlL/kuK3lv4PkvY3nva7pnaLnp6/nrYkNCuWPpuWkluWPr+S7peWPkeeOsO+8jOW6leWbvuaVsOaNruahhueahGlk5bCx5piv6L+Z5Liq5L+h5oGv5pWw5o2u5qGG55qE6KGM5Y+3DQrov5nmoLfvvIznu4/ov4fnroDljZXlpITnkIbvvIzkuKTpg6jliIbmlbDmja7lsLHlj6/ku6Xmi7zlkIjkuoYNCuS4jei/h++8jOmJtOS6juW6leWbvuaVsOaNruahhuihjOaVsOW+iOWkp++8jOaciWByIG5yb3cobWFwbnApYOihjO+8jA0K5pyA5aW95LiA5qyh5Y+q5ou85ZCI5LiA5bm055qE5pWw5o2u77yM5Lul5YWN5YaF5a2Y5rqi5Ye6DQpgYGB7cn0NCm1kYXRhIDwtIG11dGF0ZShtZGF0YSwgaWQ9cm93bmFtZXMobWRhdGEpLCBDSVRZQ049YXMuY2hhcmFjdGVyKE5BTUU5OSkpDQpgYGANCg0KDQo0LjEg5ou85ZCI5pWw5o2u5bm255S75Zu+77yMDQrnlKjkuK3mloflkI3np7DlsIboh6rmnInmlbDmja7kuI7lupXlm77kv6Hmga/mlbDmja7mi7zlkIjvvIwNCueUqGlk5bCG5bqV5Zu+5L+h5oGv5LiO5bqV5Zu+5pWw5o2u5qGG5ou85ZCI77yMDQrov5nmoLflsLHog73nlKhnZ3Bsb3Qy55S75Zu+5LqGDQrosIPmlbTlpb3phY3oibLvvIzmlbDmja7moIfnrb7kvY3nva7vvIzmoIflm77lrozmlbTlkI7lsLHlj6/ku6Xkv53lrZjkuoYNCmBgYHtyfQ0KcGxvdHllYXIgPC0gZnVuY3Rpb24oeWVhcil7DQogIG1kYXRhLnkgPC0gbGVmdF9qb2luKG1kYXRhLCBmaWx0ZXIoY3NkYXRhLCBkYXRheWVhcj09eWVhciksIGJ5PSdDSVRZQ04nKQ0KICBtYXBucC55IDwtIGxlZnRfam9pbihtYXBucCwgbWRhdGEueSwgYnk9J2lkJykNCiAgDQogIHBtIDwtIGdncGxvdChkYXRhID0gbWFwbnAueSkgDQogIHBtIDwtIHBtICsgICBnZW9tX3BvbHlnb24oYWVzKHggPSBsb25nLCB5ID0gbGF0LCBmaWxsPWxldmVsLCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAiYmxhY2siKQ0KICBwbSA8LSBwbSArIGxhYnMoIHggPSAi57uP5bqmIiwgeSA9ICLnuqzluqYiLHRpdGxlID1wYXN0ZSh5ZWFyLCflubQnKSkNCiAgcG0gPC0gcG0gKyB0aGVtZShsZWdlbmQucG9zaXRpb249YygwLjEsMC4xNSkpDQogIHBtIDwtIHBtICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNiX3BhbGV0dGUsIG5hbWUgPSAi6auY6LSo6YeP5Y+R5bGV5rC05bmzIiwgbGFiZWxzID0gc3RkbmFtZXMpDQogIHByaW50KHBtKQ0KICBnZ3NhdmUocGFzdGUoeWVhciwgJy5wbmcnKSwgcG0sIHdpZHRoID0gMTAsIGhlaWdodCA9IDgsIGRwaSA9IDE1MCkNCn0NCmBgYA0KDQo1LjEg5b6q546v5omn6KGM6ZyA6KaB5L2c5Zu+55qE5bm05Lu977yM5Y2z5Y+v5b6X5Yiw5aSa5bm055qE5Zu+5LqGDQpgYGB7cn0NCmZvcih5ZWFyIGluIHllYXJzKSBwbG90eWVhcih5ZWFyKQ0KYGBgDQoNCiMjIOWQjuiusA0KVGVhbUxlYWRlcueahOagh+WHhuaenOeEtuS4jeWQjOWHoeWTje+8jOaJgOS7peWlueaYr1RlYW1MZWFkZXLvvIwNCjjlj7fkuIDml6nvvIzmiJHlj4jnlLvkuoYy5Liq5bCP5pe25bCG5Zu+UOaIkOWPr+S7peeUqOeahOagt+WtkA0KDQojIyDlnLDlm77mnYLosIgNCuWFtuWunuaIkeS7rOeUu+S4reWbveeahOWbvuimgeeDpuatu+S6hu+8jOWboOS4ulLlubbmsqHmnInoh6rluKbkuK3lm73lhoXpg6jnmoTlupXlm77vvIwNCuWmguaenOimgeeUu+e+juWbveeahOWcsOWbvueugOWNleatu+S6hu+8jOWboOS4uuW3suaciVLljIXlhoXnva7kuobnvo7lm73nmoTlupXlm77vvIwNCuavlOWmgueUu+S4que+juWbveWQhOW3nueahOWcsOWbvu+8jOWPquimgeivu+WFpeebuOW6lOaVsOaNrueUu+S4i+WwsU9LDQrmraTpg6jliIblj4LogIPoh6oqRXJpYyBDLiBBbmRlcnNvbiDnmoQgTWFraW5nIE1hcHMgd2l0aCogUjxodHRwOi8vZXJpcWFuZGUuZ2l0aHViLmlvL3JlcC1yZXMtd2ViL2xlY3R1cmVzL21ha2luZy1tYXBzLXdpdGgtUi5odG1sPg0KYGBge3J9DQpzdGF0ZXMgPC0gbWFwX2RhdGEoInN0YXRlIikNCmdncGxvdChkYXRhID0gc3RhdGVzKSArIA0KICBnZW9tX3BvbHlnb24oYWVzKHggPSBsb25nLCB5ID0gbGF0LCBmaWxsID0gcmVnaW9uLCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAid2hpdGUiKSsNCiAgZ3VpZGVzKGZpbGw9RkFMU0UpDQpgYGANCg0K6ICM5LiU77yM5pu05Yqg5Y+Y5oCB55qE5piv77yM576O5Zu955qE5Zyw5Zu+5pWw5o2u5Y+v5Lul5YiG5Y6/77yIcHPvvIznvo7lm73msqHmnInlnLDnuqfooYzmlL/ljLrliJLvvInvvIwNCua8lOekuuS4gOS4qu+8jOaKiuWKoOW3nuWQhOWOv+eahOWbvueUu+S4gOS4i++8jOWwseaYr+i/meS5iGVhc3kNCmBgYHtyfQ0KY291bnRpZXMgPC0gbWFwX2RhdGEoImNvdW50eSIpDQpjYV9jb3VudHkgPC0gc3Vic2V0KGNvdW50aWVzLCByZWdpb24gPT0gImNhbGlmb3JuaWEiKQ0KZ2dwbG90KGRhdGEgPSBjYV9jb3VudHkpICsgDQogIGdlb21fcG9seWdvbihhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGZpbGwgPSByZWdpb24sIGdyb3VwID0gZ3JvdXApLCBjb2xvciA9ICJ3aGl0ZSIpKw0KICBndWlkZXMoZmlsbD1GQUxTRSkNCmBgYA0KDQrkvYbmmK/vvIzlvojmirHmrYnvvIzlpoLmnpzmg7Por7vkuK3lm73nmoTmmK/msqHmnInnmoTvvIzlpoLkuIvvvJoNCg0KYGBge3J9DQpjaGluYSA8LSBtYXBfZGF0YSgiY2hpbmEiKQ0KYGBgDQoNCuS4jei/h+eUqOi/meS4quaVsOaNrui/mOWPr+S7peeUu+S4lueVjOWcsOWbvuWAkuaYr+ayoemXrumimA0KYGBge3J9DQp3b3JsZCA8LSBtYXBfZGF0YSgid29ybGQiKQ0KZ2dwbG90KGRhdGEgPSB3b3JsZCkgKyANCiAgZ2VvbV9wb2x5Z29uKGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZmlsbCA9IHJlZ2lvbiwgZ3JvdXAgPSBncm91cCksIGNvbG9yID0gIndoaXRlIikrDQogIGd1aWRlcyhmaWxsPUZBTFNFKQ0KYGBgDQoNCj4g546w5Zyo5pivYHIgZGF0ZSgpYO+8jOivpeWwseWvneS6hu+8jGJ5ZSBteTMwNQ0KDQoNCg==