查看原文
其他

一个小案例,教你如何从数据抓取、数据清洗到数据可视化

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

一篇小短文了,囊括数据抓取、数据清洗、数据呈现等全过程,数据主要展示2016年我国top100地级市GDP、增长率、及地区分布密度图三个维度信息。


library(plyr)

library(rvest)

library(stringr)

library("data.table")

library(dplyr)


随便找的一篇微信短文,复制网址链接直接在浏览器打开


readurl<-"http://mp.weixin.qq.com/s?__biz=MzI1ODM5NTQ1Mw==&mid=2247484083&idx=1&sn=ba4f4b10af3e4d6ed45f4d04edc30980&chksm=ea099ee1dd7e17f717afffdb3a3ff82c6e4e6bd351251601f0968c792b7e7cb5cdf084fb86a8&mpshare=1&scene=23&srcid=02039mlTmLqMxQEnb4CnUrK3#rd"


用rvest简单提取文本内容


web<-read_html(readurl,encoding="UTF-8")

a<-web%>%html_nodes("p")%>%html_text()




数据抓取阶段完毕,以下转入数据清洗阶段:


#------------------------------------------------------------------------------------------------------


仔细观察该文本向量可以发现,我们需要的城市数据都是以数开头(1~3位不等),其中第七行也是一数据字开头(2017年1月20日),使用正则表示进行精准匹配,并将所有标点符号(记得是中文标点)替换成逗号(英文),方便之后作为分列拆分依据(也可以自定义拆分的符号)


a<-grep("^\\d{1,3}\\D",a,value=TRUE)

a<-gsub("(\\(|\\)|\\,|\\:)",",",a)



由于四个直辖市文本行与其他城市相比,缺失一个省级标签,为使之后拆分顺利完成,需要将其修改与其他城市一致。


a[1]<-"1.上海,上海1,26688亿元,同比增长6.7%,人口,2415万,"

a[2]<-"2.北京,北京1,24541亿元,同比增长6.7%,人口,2171万,"

a[5]<-"5.天津,天津1,17800亿元,同比增长9%,人口,1547万,"

a[6]<-"6.重庆,重庆1,17010亿元,同比增长10.7%,人口,3372万,"


剔除中文冗余文字


dataA<-gsub("((亿元)|(同比增长)|(人口)|(万))","",a)


字符串拆分,使用stringr中的str_split函数进行拆分,使用plyr中的ldply函数进行数据框转化,然后对列字段重命名,重排序。


temp1<-str_split(dataA,",")

result1<-ldply(temp1,.fun=NULL)


Error in list_to_dataframe(res, attr(.data, "split_labels"), .id, id_as_factor) : 

  Results do not have equal lengths


以上语法出错,提示长度不等,用函数查看具体哪一行出现不等长的情况。


m<-c()

for (i in 1:length(temp1)) m[i]<-length(temp1[[i]])

grep("6",m)

[1] 35 36


查看具体情况

dataA[35:37]

[1] "35.温州,浙江3,5110,8%,919,"          "36.绍兴,浙江4,4800,5%,501,"         

[3] "37.鄂尔多斯,内蒙古1,4678,7.3%,,201,"


原来是倒数第二个分割点少了一个逗号,重新补全,使其等长。


dataA[35]<-"35.温州,浙江3,5110,8%,,919,"

dataA[36]<-"36.绍兴,浙江4,4800,5%,,501,"


再次运行拆分函数:

temp1<-str_split(dataA,",")

result1<-ldply(temp1,.fun=NULL)

names(result1)<-c("city","province","gdp","ratio","blank1","scale","blank2")

result1<-result1[,-c(5,7)]


提取城市名称字段:

wh<-regexpr("[0-9]{1,3}",result1[,1])

order<-substring(result1[,1],wh,wh+attr(wh,"match.length")-1)

city<-substring(result1[,1],attr(wh,"match.length")+2)


nchar(city)>1


为防止提取的城市名称不全,查看下是否有少于一个字符的名称:


  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [15]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [29]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [43]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [57]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [71]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [85]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

 [99]  TRUE  TRUE


第92名宿迁因为少了一个句号,只提取了一个字符,立即补全(之后要使用城市名称提取经纬度,否则会失败)


city[92]<-"宿迁"


合并:

result<-data.frame(order,city,result1)

result<-result[,-3]


提取省份名称、省内排名字段


wm<-regexpr("[0-9]{1,2}",result[,3])

prov<-substring(result[,3],1,wm-1)

scope<-substring(result[,3],wm,wm+attr(wh,"match.length")-1)


替换百分号(坑爹啊,R不支持百分号显示,一律识别为文本)

result$ratio<-sub("%","",result$ratio)

result$ratio<-as.numeric(result$ratio)

result$ratio<-result$ratio/100


合并并重排序列字段

resultm<-data.frame(prov,scope,result)

resultm<-resultm[,c(3,4,1,2,6,7,8)]


查看数据框字段属性,不符号要求需要重新定义属性


str(resultm)

resultm$order<-as.numeric(resultm$order)

resultm$city<-as.character(resultm$city)

resultm$prov<-as.character(resultm$prov)

resultm$scope<-as.numeric(resultm$scope)

resultm$gdp<-as.numeric(resultm$gdp)

resultm$scale<-as.numeric(resultm$scale)


按照排名排序

resultm<-arrange(resultm,order)

resultm$order[92:100]<-92:100


至此数据清洗阶段完毕,以下转入数据呈现

#-----------------------------------------------------------------------------------------------


分布密度图:


library(ggplot2)      

library(plyr)         

library(maptools) 

library(ggmap) 

library(REmap)


china_map<-readShapePoly("c:/rstudy/bou2_4p.shp")

china_map1 <- fortify(china_map)

data<-get_geo_position(resultm$city)

data$lon<-as.numeric(data$lon)

data$lat<-as.numeric(data$lat)


ggplot()+

geom_polygon(data=china_map1,aes(x=long,y=lat,group=group),fill="white",col="grey60",size=.3)+

geom_polygon(data=data,aes(x=lon,y=lat,fill = ..level..), stat="density_2d", alpha = .3, color = NA)+

coord_map("polyconic") +

scale_fill_gradient2( low = "white",mid="yellow", high = "red")+

theme_nothing()



gdp总量分布图:

data1<-inner_join(resultm,data)


ggplot()+

geom_polygon(data=china_map1,aes(x=long,y=lat,group=group),fill="white",col="grey60",size=.3)+

coord_map("polyconic") +

geom_point(data=data1, aes(x =lon,y =lat,size=gdp), alpha=0.6,shape=21, fill="red",colour="white")+ 

scale_size_area(max_size=12)+  

theme_nothing()



增长率分布图:


ggplot()+

geom_polygon(data=china_map1,aes(x=long,y=lat,group=group),fill="white",col="grey60",size=.3)+

geom_point(data=data1, aes(x =lon,y =lat,size=ratio,fill=ratio), alpha=0.6,shape=21, colour="white")+ 

scale_fill_gradient2(low="#0E4E75", mid="#BFBEBE", high="red", midpoint=median(na.omit

(data1$ratio)))+   

coord_map("polyconic") +

scale_size_area(max_size=6)+  

theme_nothing()



麻雀虽小,五脏俱全,数据可视化也是一样!地图素材在魔方学院QQ群贡献的rstudy文件中,其他作图数据可通过运行代码获得~


我是分割线~


欢迎关注魔方学院QQ群


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

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