查看原文
其他

这是一篇很务正业的可视化推送~(上篇)

2017-03-16 小魔方 数据小魔方

自带学习R语言以来,从来没用把这些技能用在自己的专业方向上,说好的学以致用呢~


最近看到的一篇微信公众号推文,内容是关于山东省各县(细化到137个县级行政区)2016年的GDP规模、公共预算收入规模及其增速指标,数据质量还不错,是山东省发改委公布的。


http://mp.weixin.qq.com/s/Sk4fIh3-ykcNK8uP0gZryw


感觉自己终于离专业方向近了一些(本人学财政的),数据就在眼前,这次机会一定要抓住了。


数据虽然质量不错,但是苦于手头没有最新的山东省县级地图素材(之前练习用的SHP素材都是很古老的素材,使用市级范围没啥问题,但是县级行政单位变更太快了,根本没法用)。所以这篇文章写作过程特别艰难~


我用了半个上午爬取并整理数据,却用了两天时间寻找地图素材、最终找到了山东省17个地级市的json素材(还不会合并json数据),找到了个在线json转shp的平台,用17个json文件拼接成一个 完整的山东省地图,然后导出shp数据,这才搞定了县级地图工作。(想想也是太执着了~)


本篇文章主要主要还是演示地图可视化为主,其中包含基础的数据抓取、数据清洗、数据聚合、变量结构和ggplot图层语法,最终得到7福高质量的数据地图。


以下是本文需要用到的包:


library(XML)

library(RCurl)

library(stringr)

library(dplyr)

library(plyr)

library(ggplot2)      

library(maptools)   

library(Cairo)        

library(RColorBrewer) 

library(xlsx)

library(rjson)

library(rgdal)

library(data.table)

library(tidyr)

library(grid)

library(showtext)

library(sqldf)


数据抓取过程:


url<-"http://mp.weixin.qq.com/s/Sk4fIh3-ykcNK8uP0gZryw"

Name<- getURL(url,.encoding="utf-8")%>%htmlParse(encoding="UTF-8")%>%getNodeSet("//strong/span")   

title<-grep("按",laply(Name,xmlValue,trim=T),value=T);title


tbls<-readHTMLTable(url,header=TRUE,trim=TRUE)


names(tbls)<-title;names(tbls)

sapply(tbls,nrow)

[1] "按公共财政预算收入规模:"     "按公共财政预算收入增长幅度:"

[3] "按GDP规模:"                  "按GDP增长幅度:"             

[5] "按人均GDP:" 


以下数据网页中五张表格的提取过程:


BudgetScale<-tbls$`按公共财政预算收入规模:`[-1];names(BudgetScale)<-c("Country","BudgetScale")

BudgetScale$Country<-as.character(BudgetScale$Country)

BudgetScale$BudgetScale<-as.numeric(as.character(BudgetScale$BudgetScale))


BudgetGrowth<-tbls$`按公共财政预算收入增长幅度:`[-1];names(BudgetGrowth)<-c("Country","BudgetGrowth")

BudgetGrowth$Country<-as.character(BudgetGrowth$Country)

BudgetGrowth$BudgetGrowth<-as.numeric(as.character(BudgetGrowth$BudgetGrowth))


GDPScale<-tbls$`按GDP规模:`[-1];names(GDPScale)<-c("Country","GDPScale")

GDPScale$Country<-as.character(GDPScale$Country)

GDPScale$GDPScale<-as.numeric(as.character(GDPScale$GDPScale))


GDPGrowth<-tbls$`按GDP增长幅度:`[-1];names(GDPGrowth)<-c("Country","GDPGrowth")

GDPGrowth$Country<-as.character(GDPGrowth$Country)

GDPGrowth$GDPGrowth<-as.numeric(as.character(GDPGrowth$GDPGrowth))



PerGDPGrowth<-tbls$`按人均GDP:`[-1];names(PerGDPGrowth)<-c("Country","PerGDPGrowth")

PerGDPGrowth$Country<-as.character(PerGDPGrowth$Country)

PerGDPGrowth$PerGDPGrowth<-as.numeric(as.character(PerGDPGrowth$PerGDPGrowth))


BudgetScale<-arrange(BudgetScale,Country)

BudgetGrowth<-arrange(BudgetGrowth,Country)

GDPScale<-arrange(GDPScale,Country)

GDPGrowth<-arrange(GDPGrowth,Country)

PerGDPGrowth<-arrange(PerGDPGrowth,Country)


本来137个县级行政区的名称应该是一致的,但是网页中公布的数据名称不一致,所以没法合并,需要自己集合最新的行政区划名称手动修改,费老大劲!


先将五张表格的数据写入一个工作薄中,然后手动修改:


write.xlsx(BudgetScale,"D:/R/File/shddata.xlsx",sheetName="BudgetScale",append=FALSE,row.names=FALSE)

write.xlsx(BudgetGrowth,"D:/R/File/shddata.xlsx",sheetName="BudgetGrowth",append=TRUE,row.names=FALSE)

write.xlsx(GDPScale,"D:/R/File/shddata.xlsx",sheetName="GDPScale",append=TRUE,row.names=FALSE)

write.xlsx(GDPGrowth,"D:/R/File/shddata.xlsx",sheetName="GDPGrowth",append=TRUE,row.names=FALSE)

write.xlsx(PerGDPGrowth,"D:/R/File/shddata.xlsx",sheetName="PerGDPGrowth",append=TRUE,row.names=FALSE)


因为以上五个表格所用到的行政区划名称不完全相同,需要手动各县级行政区划对应的隶属地级市名称才能进行列合并。


以下是我从网络上找到并整理的山东省17地级市,137县级(包含县级市)行政单位的代号,名称,经纬度信息。


setwd("D:/R/mapdata/Country/shandong")

shandong_city<-read.xlsx("City.xlsx",sheetName="City",header=T,encoding='UTF-8',stringsAsFactors=FALSE)

shandong_district<-read.xlsx("City.xlsx",sheetName="District",header=T,encoding='UTF-8',stringsAsFactors=FALSE)


shandong_district<-

unite(shandong_district,address,City,Name,sep="")

shandong_district<-transform(shandong_district,Adress=paste0("山东省",shandong_district$address))[,-1][,c(4,1,2,3)]

names(shandong_district)[1]<-"address"


通过以上shandong_district表中的城市、县级市名称字段合理规范以上五张表中的县级行政单位名称,总最终合并至表6——shandongdata注意五张表在同一个工作薄中。


---------------------------------------------------------------------------------------------------------------

解析经纬度地址:这里调用百度地图的API解析县级市的经纬度地址:

(大家最好自己去注册百度地图开发者,然后申请免费秘钥)


baidu_lng <- c()

baidu_lat <- c()

ak<-"X8zlxPUdSe2weshrZ1WqnWxb43cfBI2N"

address<-shandong_district$address

for(location in address){

url<-paste("http://api.map.baidu.com/geocoder/v2/?ak=",ak,"&callback=renderOption&output=json&address=",location,sep="")

url_string <- URLencode(url)                  

json<- readLines(url_string, warn=F)         

geo <- fromJSON(substr(json,regexpr("\\(",json)+1,nchar(json)-1))  

lng<-geo$result$location$lng

lat<-geo$result$location$lat                 

baidu_lng<-c(baidu_lng,lng)                 

baidu_lat<-c(baidu_lat,lat)

}

result<-data.frame(address=address,longitude=baidu_lng,latitude=baidu_lat,stringsAsFactors=FALSE)


将县级市数据与经纬度数据合并:


shandong_district_data<-merge(shandong_district,result,by="address")[,-c(3,4)]

names(shandong_district_data)[3:4]<-c("lon","lat")

shandong_district_data$address<-as.character(shandong_district_data$address)

shandong_zhibiao_data<-read.xlsx("shddata.xlsx",sheetName="Shandongdata",header=T,encoding='UTF-8',stringsAsFactors=FALSE)

names(shandong_zhibiao_data)[2]<-"address"

shandong_district_data<-merge(shandong_district_data,shandong_zhibiao_data,by="address")


以上得到了山东省所有县级行政单位的点坐标信息。

--------------------------------------------------------------------------------------------------------------

读图背景素材导入:

素材一:山东省县级地图素材:

mymap<-readOGR(".","map",encoding = "UTF-8",verbose=FALSE)

myShape <- fortify(mymap)  

x <- mymap@data

names(x)[3]<-"Code"   

xs <- data.frame(x,ID=seq(0:139)-1)[,c(3,8)]

shandong_district_map_data<-merge(myShape,xs,by.x="id",by.y="ID",type="full")[,-c(5,6)]


很遗憾,我们从以上素材中所提取的城市名称数据,可能涉及到编码的问题,中文全部成为了乱码,这样我们前期整理的山东省GDP及公共财政相关数据的中名称便无法与该地图进行匹配,好在行政区代码还在,这样我们就可以从之前找到行政区划代码和名称信息进行匹配。


将县级行政区地图与县级市进行匹配,获得信息完整的县级地图数据。


shandong_district_map_data<-merge(shandong_district_map_data,shandong_district_data[,-c(3,4)],by="Code",all.x=TRUE)

shandong_district_map_data<-shandong_district_map_data[order(shandong_district_map_data$order),]


素材2:山东省市级地图素材:


CHN_adm2 <- readOGR("D:/R/rstudy/CHN_adm/CHN_adm2.shp") 

CHN_adm2_1 <- fortify(CHN_adm2)  

CHN_adm2_1$id<-as.numeric(CHN_adm2_1$id)

shx <- CHN_adm2@data          

shxs <- data.frame(shx,id=seq(0:344)-1)        

china_map_data <- join(CHN_adm2_1,shxs,type="full") 

shandong_city_map_data<-subset(china_map_data,NAME_1==c("Shandong"))[,c(1,2,7,14)]

mydata<-read.csv("D:/R/rstudy/State/huanbohai.csv",header=T)[,-3] 


#匹配市级行政单位信息:

shandong_city_map_data <-join(shandong_city_map_data,mydata,by="NAME_2",type="left")

--------------------------------------------------------------------------------------------------------


接下来整合指标信息与地图作图数据:


山东省市级地图作图数据:


因为我们之前获取的指标数据是按照县级行政区划整理的,这里需要使用聚合函数,整理成市级的。因为增长比率数据汇总聚合后意义不大,即便是平均值也不是很有意义,所以这里只用市级的公共预算支出和GDP数据。


shandongdata<-data.table(shandong_zhibiao_data)

shandongnewdata<-shandongdata[,.(SUM_BudgetScale=sum(BudgetScale),SUM_GDPScale=sum(GDPScale)),by=City]

shandong_city_map_data<-merge(shandong_city_map_data,shandongnewdata,by.x="city",by.y="City") 

shandong_fill_map_data<-shandongnewdata

shandong_fill_map_data$city<-paste0(shandong_fill_map_data$City,"市")

shandong_fill_map_data<-shandong_fill_map_data[,c(1,4,2,3)]

shandong_fill_map_data<-merge(shandong_fill_map_data[,-1],shandong_city,by.x="city",by.y="City")

shandong_fill_map_data<-shandong_fill_map_data[,c(1,4,5,6,2,3)]


---------------------------------------------------------------------------------------------------------------

现在所有的数据已经整理完毕,我们一共得到了四张有用的数据集:


市级地图数据——shandong_city_map_data(含城市指标)

县级地图数据——shandong_district_map_data(含17个地级市指标及经纬度)

市级指标数据——shandong_fill_map_data(含城市经纬度及两个指标:GDP规模和公众预算规模)

县级指标数据——shandong_district_data(含137个行政县指标及经纬度和五个指标数据,GDP规模、GDP增速,人均GDP增速,预算规模、预算增速)。


因为地级市数据限制,只有两个指标(GDP规模和预算规模),所以,最多只能制作两张地图。

县级行政区数据比较齐全,这里计划的呈现的维度是GDP规模与GDP增速,GDP规模与人均GDP增速,GDP增速与人均GDP增速。预算规模和预算增速。合计一共四张图。


----------------------------------------------------------------------------------------------------


今天我才知道,微信推文有字数限制,20000字以内,我靠我竟然一篇 推送写了两万多字,晕倒~—~


篇幅所限,下半部分转第二篇:




欢迎关注魔方学院QQ群


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存