查看原文
其他

R语言天气可视化应用

2017-04-09 张丹 R语言中文社区

(由于字数限制,省略部分代码,完整请阅读原文)


前言

在很多人看来,R语言还只是个玩具,完全不具备企业级应用的能力。说这些话的人,根本就不了解R语言,更不清楚如何做企业级应用开发。从我最早接触R语言时,就把R做为可视化引擎嵌入到了晒粉丝的微博应用中;后来又开发了数据挖掘算法竞赛网站,并把R语言做为算法引擎,并支持在线编程及运行;我做的第三个R语言应用就是本文要给大家分享的每日中国天气微博应用,这次同样是把R做为可视化引擎,并让R完成爬虫、XML文档解析及数据处理等的任务;当然,我还实现了第四个、第五个、第六个以R为核心的应用,都是量化投资方面的,会在下一本书《R的极客理想-量化投资篇》再介绍给大家。

从我的使用经验来看,R语言已经具备了企业级应用的能力,但我并不是要用R语言完成所有编程任务。在我的项目环境中,大都是多种编程语言配合使用的,只有发挥各自语言的特性优势,才是未来的发展方向。

本文所介绍的每日中国天气微博应用开发,将分为3篇介绍R语言和PHP语言的混合编程,第一篇为R语言功能实现,第二篇为R包开发,第三篇为用PHP构建微博应用。本文是第一篇。


目录

  1. 项目介绍

  2. 系统架构设计

  3. R语言程序现实


1. 项目介绍

谈到多语言混编,同如在计算机领域跨学科一样,是我所一直倡导一种工作模式。当编程语言百花齐放,各种细分市场的小众语言如雨后春笋般地成长起来,比起通用型编程语言来说,这些小众语言在特定的领域中有着非常明显的优势。 比如统计应用,如果用Java写个逻辑回归程序感觉深不见底,而用R语言实现逻辑回归就是个很平常的一件事情。 再比如做一个Web网站,用PHP或Nodejs实现轻而易举,如果用Java做不仅代码量大,而且程序复杂。 所以,对于一个应用来说,一种通用的语言并不一定是最好的解决方案,如果能实现多种语言的结合,那么你做出来的应用可以很酷,很不一样!

对于本文要介绍的 每日中国天气 这个新浪微博应用,就是一种多语言混编的实现。


项目介绍

这个项目的出发点很简单,就是通过可视化技术,展示中国每个省份的天气情况,给准备旅游的朋友,提供一种出行的提示。

要做实现这个应用,我们首先要列出,要实现哪些功能,会遇到哪些问题等。

  • 天气数据:数据从哪里找到,如何下载,如何存储。

  • 定时任务:天气数据需要每日更新,图片需要每日新生成。

  • 地图和天气可视化:要把中国行政区图和天气数据结合在一起画图,让用户一眼就能看明白。

  • Web展示:通过可视化技术,我们生成的只是一张静态图片,如何发布到Web端进行展示。

  • 微博:通过结合新浪微博,让更多的用户看到并使用这个应用。

  • 用户交互:用户可以查看不同日期、不同类型的图片,用户还可以通过微博分享。

  • 虽然是个很小的应用,但五脏俱全,我们也需要完整的思考,如何才能实现这个应用呢!

2. 系统架构设计

从上面的功能描述中,单独使用一种语言也可以实现的。 如果单独用PHP开发,做一个Web网站非常容易,连接新浪微博也有现成的SDK可以调用,爬取数据及存储也不麻烦,那么如何实现地图和天气数据的可视化,似乎就是卡在这里了。 如果单独用R开发,爬取数据及存储同样很容易实现,地图和天气数据的可视化也是很方便就能画出来,但是用R做Web网站,那就会遇到很大的瓶颈了,因为R是单线程同步的计算模型,Web应用的高并发特点,会直接让R程序崩溃的。 所以,综合上面的问题,如果R语言和PHP语言能结合在一起使用,不仅能避开每种语言不擅长的地方,还能在擅长的领域发挥出每种语言的特性,我们将通过多语言的混编技术做出很不一样的应用来。

为了实现应用的功能需求,我们要设计一套系统架构。


系统架构解释:

  • 通过定时器启动爬虫程序,到Yahoo的天气数据源下载数据。

  • 爬虫下载数据到本地服务器进行解析,存储应用相关的数据到CSV文件。

  • 可视化程序,读入天气数据及地图数据,生成静态的图片作为可视化输出。

  • 最终用户通过新浪微博,加载Web应用,看到了可视化生成的静态图片。

  • 最终用户通过新浪微博分享了这个应用,让更多的人看到这个应用。

下面按照语言的优势,把应用架构以语言的特性来划分,让R语言实现爬虫、处理数据和可视化,让PHP完成Web开发、新浪API接入和用户交互。


由于我们这个应用,不需要让R和PHP直接进行通信,那么复杂度就会变得小很多了,像我之前做的晒粉丝应用,是3种语言的结合包括了R, PHP, Java,通过Java实现中间程序的调度,让R和PHP能够实现通信。

我们通过语言的划分,就可以扬长避短,让每种语言在最擅长的领域,完成最擅长的事情。

对于后台技术应用,定时器可以用Linux系统的CRON实现;然后用R语言程序来爬取数据,通过RCurl包来完成;爬取后的数据为XML格式,再通过R语言用XML包进行解析,以CSV格式进行本地存储;接下来,再用R语言处理数据,加载地图包ggmap、mapdata、maptools,最后配合plot()函数实现图片的输出,保存在本地服务器上。

对于前端的PHP应用来说,用PHP做一个Web网站很简单,使用YII快速开发框架;用PHP的新浪微博SDK进行API操作,实现新浪登陆,新浪分享等功能;最后Nginx + Spawn构建出PHP运行时环境,让Nginx完成负载均衡和图片加载,并配合PHP的访问规则,实现功能的切换。

合理的架构设计加上适应的语言的分工,就能轻松实现了 每日中国天气 这样的一个微博应用。其实,我们可以用这种多语言混搭的方式,创建出各种创新型的网站应用,但前提是先能掌握多种语言。

这里我想再多说一句,通常我认识的程序员,都是在自己的技术领域中无限畅快,一旦他们掌握了一种语言的核心技术,并有了一些开发经验后,往往不愿意再去学第二种语言。 对这些人来说,总觉得自己就是世界的中心,自己有能力实现的所有的功能。这些也都是有理想的程序员,只不过他们进入了一个误区,被现有的技术给迷住了,看不到、也不愿意看到外面的世界已经变了。我曾经就是这样的!

我承认Java是一种无所不能的编程语言,但是如果你所有程序都用Java实现,难道不觉得又费时又费力吗?通用性越强,反而专有领域的应用性就越差。这也是我从Java单一的技术路线走出来的原因。其实,在精通一门语言后,再去学习另外一门新的语言,就不是那么难了。但如果只是沉醉于已掌握的技术,很快就会被一代新人,一代新工具所超越的。


3. R语言程序现实

下面就开始介绍R语言的部分程序开发,在写代码之前,我们需要先梳理开发流程,做一下程序设计,R语言都需要实现哪些功能,用到哪些第三方R包。

我用一幅图来说明程序之间的调用关系,R语言的程序实现一共包括了6个部分,爬虫程序、本地存储,地图加载、数据可视化处理、生成静态图、生成可交互的静态图。


上图中,分别标出了每个步骤用的到R包或者功能函数,同时我们可以按照这个流程来定义功能函数,这样我们就把整个应用程序都规划好,最后再对应的写代码就不难了。


3.1 爬虫部分

对于爬虫部分来说,就是定时下载每个城市的或地区的天气数据,并解析数据,只保留我们需要的字段,并以CSV的格式存储。互联网上有很多免费公开的天气数据源,对我来说,最方便的数据源有2个,一个是Yahoo的天气数据,另一个Google的天气数据,但由于Google的API从中国大陆会经常会访问不到,所以我在这里选择Yahoo的天气数据源进行访问。

yahoo天气数据源的访问地址,如下所示。

http://weather.yahooapis.com/forecastrss?w=WOEID

其中WOEID代表城市对应的代码,如果想查看北京的天气数据,北京对应的WOEID为2151330,可以访问用浏览器访问 http://weather.yahooapis.com/forecastrss?w=2151330 。

我们通过浏览器打开地址,就可以看到这个数据,数据是以XML格式进行发布的。



我们要解析这个XML文件,从中找到我们需要数据进行提邓。在R语言中,通过RCurl包实现HTTP的网络访问,抓取到整个的XML文档数据,然后通过XML包解析XML文档的DOM树,就能找到我们需要的数据了。

本文的系统环境

  • Win7 64bit

  • R: 3.1.1 x86_64-w64-mingw32/x64 (64-bit)

当我们把业务逻辑和技术实现都想清楚了,就可以动手写代码了,只十几行代码就能完成爬虫和XML文档解析的功能。


> library(RCurl)        # 加载类库
> library(XML)
>
> getWeather<-function (x){
+     url<-paste('http://weather.yahooapis.com/forecastrss?w=',x,'&u=c',sep="")       # yahoo的数据源地址
+     doc = xmlTreeParse(getURL(url),useInternal = TRUE)                              # 解析XML文档
+
+     ans<-getNodeSet(doc, "//yweather:atmosphere")
+     humidity<-as.numeric(sapply(ans, xmlGetAttr, "humidity"))                       # 温度
+     visibility<-as.numeric(sapply(ans, xmlGetAttr, "visibility"))                   # 能见度
+     pressure<-as.numeric(sapply(ans, xmlGetAttr, "pressure"))                       # 气压
+     rising<-as.numeric(sapply(ans, xmlGetAttr, "rising"))                           # 气压变动
+
+     ans<-getNodeSet(doc, "//item/yweather:condition")
+     code<-sapply(ans, xmlGetAttr, "code")                                           # 天气情况
+
+     ans<-getNodeSet(doc, "//item/yweather:forecast[1]")
+     low<-as.numeric(sapply(ans, xmlGetAttr, "low"))                                 # 最高气温
+     high<-as.numeric(sapply(ans, xmlGetAttr, "high"))                               # 最低气温
+
+     print(paste(x,'==>',low,high,code,humidity,visibility,pressure,rising))
+     cbind(low,high,code,humidity,visibility,pressure,rising)                        # 以data.frame格式返回
+ }

运行程序,查看返回结果。


> w<-getWeather(2151330)    # 执行爬虫程序
[1] "2151330 ==> 9 13 21 59 4.1 1016.4 0"

> w                         # 返回的结果集
    low high code humidity visibility pressure rising
[1,] "9" "13" "21" "59"     "4.1"      "1016.4" "0"

对于功能需求来说,一个城市只保存7个字段就行了,其他的XML文档的数据可以全部过滤掉不管。


3.2 本地存储

我们通过爬虫下载并过滤后的数据,已经是data.frame的格式了,通过write.csv()函数就把这些数据输出到本地文件系统中保存起来,做为数据的备份。

我们在处理本地存储的过程中,除了要生成一个CSV文件,还包括了 文件命名,把多个城市的数据合并到一个文件存储的问题。下面我们需要再定义两个函数,filename()函数用于新生成文件的命名,loadDate()函数用于多个城市数据的加载,合并在一个文件中保存。

城市列表应该是我们需要提单准备好的,我这里只选取了中国的34个城市作为我们要获得的城市天气数据的信息。如果想爬取更多的城市天气数据的信息,那么补充这个列表就行了。

城市列表数据文件WOEID.csv。

beijing,2151330,北京,北京市,116.4666667,39.9
shanghai,2151849,上海,上海市,121.4833333,31.23333333
tianjin,2159908,天津,天津市,117.1833333,39.15
chongqing,20070171,重庆,重庆市,106.5333333,29.53333333
harbin,2141166,哈尔滨,黑龙江省,126.6833333,45.75
changchun,2137321,长春,吉林省,125.3166667,43.86666667
shenyang,2148332,沈阳,辽宁省,123.4,41.83333333
hohhot,2149760,呼和浩特,内蒙古自治区,111.8,40.81666667
shijiazhuang,2171287,石家庄,河北省,114.4666667,38.03333333
wulumuqi,26198317,乌鲁木齐,新疆维吾尔自治区,87.6,43.8
lanzhou,2145605,兰州,甘肃省,103.8166667,36.05
xining,2138941,西宁,青海省,101.75,36.63333333
xian,2157249,西安,陕西省,108.9,34.26666667
yinchuan,2150551,银川,宁夏回族自治区,106.2666667,38.33333333
zhengzhou,2172736,郑州,河南省,113.7,34.8
jinan,2168327,济南,山东省,117,36.63333333
taiyuan,2154547,太原,山西省,112.5666667,37.86666667
hefei,2127866,合肥,安徽省,117.3,31.85
wuhan,2163866,武汉,湖北省,114.35,30.61666667
changsha,26198213,长沙,湖南省,113,28.18333333
nanjing,2137081,南京,江苏省,118.8333333,32.03333333
chengdu,2158433,成都,四川省,104.0833333,30.65
guiyang,2146703,贵阳,贵州省,106.7,26.58333333
kunming,2160693,昆明,云南省,102.6833333,25
nanning,2166473,南宁,广西壮族自治区,108.3333333,22.8
lasa,26198235,拉萨,西藏自治区,91.16666667,29.66666667
hangzhou,2132574,杭州,浙江省,120.15,30.23333333
nanchang,26198151,南昌,江西省,115.8666667,28.68333333
guangzhou,2161838,广州,广东省,113.25,23.13333333
fuzhou,2139963,福州,福建省,119.3,26.08333333
taipei,2306179,台北,台湾省,121.5166667,25.05
haikou,2162779,海口,海南省,110.3333333,20.03333333
hongkong,24865698,香港,香港特别行政区,114.1666667,22.3
macau,20070017,澳门,澳门特别行政区,113.5,22.2

字段解释:

  • 第一列,城市的英文名

  • 第二列,WOEID代码

  • 第三列,城市的中文名

  • 第四列,城市所在的省中文名

  • 第五列,经度(默认为东经)

  • 第六列,纬度(默认为北纬)

用于生成数据文件的R语言的函数实现。

> filename<-function(date=Sys.time()){            # 文件根据日期来命名
+     paste(format(date, "%Y%m%d"),".csv",sep="")
+ }

> loadDate<-function(date){                       # 读取城市列表,调用爬虫函数,合并数据保存到一个文件中。
+     print(paste('Date','==>',date))
+     city<-read.csv(file="WOEID.csv",header=FALSE,fileEncoding="utf-8", encoding="utf-8")  # 加载城市列表
+     names(city)<-c("en","woeid","zh",'prov','long','lat')
+     city<-city[-nrow(city),]
+
+     wdata<-do.call(rbind, lapply(city$woeid,getWeather))
+     w<-cbind(city,wdata)
+     write.csv(w,file=filename(date),row.names=FALSE,fileEncoding="utf-8")
+ }

运行程序loadDate()的函数,程序会根据城市列表的数据,调用getWeather()函数自动爬取我们定义的所有城市的天气数据。

> date=Sys.time();date              # 选择日期
[1] "2014-10-01 13:01:08 CST"

> loadDate(date)                    # 爬取数据
[1] "Date ==> 2014-10-01 13:01:08"
[1] "2151330 ==> 9 13 21 59 4.1 1016.4 0"
[1] "2151849 ==> 18 23 30 57 9.99 1015.92 0"
[1] "2159908 ==> 12 22 30 58 9.99 1017 0"
[1] "20070171 ==> 16 22 26 79 NA 1013.6 0"
[1] "2141166 ==> 2 13 34 29 9.99 1015.92 0"
[1] "2137321 ==> 3 6 11 81 9.99 1015.92 1"
[1] "2148332 ==> 7 16 34 27 9.99 1015.92 0"
[1] "2149760 ==> 4 19 30 59 9.99 982.05 0"
[1] "2171287 ==> 12 14 11 94 2.49 982.05 2"
[1] "26198317 ==> 12 23 34 52 9.99 1015.92 2"
[1] "2145605 ==> 6 17 20 82 8 812.73 0"
[1] "2138941 ==> 3 21 32 63 9 745.01 0"
[1] "2157249 ==> 13 23 11 91 2.99 1017.9 0"
[1] "2150551 ==> 8 22 28 60 7 1016.8 0"
[1] "2172736 ==> 13 19 32 52 8 1015.92 0"
[1] "2168327 ==> 14 22 32 49 NA 1017 0"
[1] "2154547 ==> 9 18 20 88 1.59 982.05 2"
[1] "2127866 ==> 17 23 34 60 9.99 1015.92 2"
[1] "2163866 ==> 19 26 28 78 6 982.05 2"
[1] "26198213 ==> 21 28 28 65 9.99 982.05 2"
[1] "2137081 ==> 15 23 34 57 9.99 1015.92 2"
[1] "2158433 ==> 19 27 20 69 4.01 1015.92 0"
[1] "2146703 ==> 18 26 28 73 9.99 1015.92 0"
[1] "2160693 ==> 13 23 28 64 9.99 1015.92 2"
[1] "2166473 ==> 24 32 30 62 9.99 982.05 0"
[1] "26198235 ==> -1 15 30 50 NA 643.41 0"
[1] "2132574 ==> 16 23 30 53 9.99 1015.92 0"
[1] "26198151 ==> 21 27 20 75 7 1016.4 0"
[1] "2161838 ==> 25 31 28 58 8 982.05 2"
[1] "2139963 ==> 21 29 28 65 9.99 982.05 0"
[1] "2306179 ==> 24 28 28 70 9.99 982.05 0"
[1] "2162779 ==> 24 31 30 58 9.99 982.05 0"
[1] "24865698 ==> 26 30 30 59 9.99 982.05 2"

程序运行完成后,会在当前目录生成一个名字为20141001.csv文件。打开20141001.csv文件,这个文件就是接下来用于生成可视化图片的基础数据了。

"en","woeid","zh","prov","long","lat","low","high","code","humidity","visibility","pressure","rising"
"beijing",2151330,"北京","北京市",116.4666667,39.9,"9","13","21","59","4.1","1016.4","0"
"shanghai",2151849,"上海","上海市",121.4833333,31.23333333,"18","23","30","57","9.99","1015.92","0"
"tianjin",2159908,"天津","天津市",117.1833333,39.15,"12","22","30","58","9.99","1017","0"
"chongqing",20070171,"重庆","重庆市",106.5333333,29.53333333,"16","22","26","79",NA,"1013.6","0"
"harbin",2141166,"哈尔滨","黑龙江省",126.6833333,45.75,"2","13","34","29","9.99","1015.92","0"
"changchun",2137321,"长春","吉林省",125.3166667,43.86666667,"3","6","11","81","9.99","1015.92","1"
"shenyang",2148332,"沈阳","辽宁省",123.4,41.83333333,"7","16","34","27","9.99","1015.92","0"
"hohhot",2149760,"呼和浩特","内蒙古自治区",111.8,40.81666667,"4","19","30","59","9.99","982.05","0"
"shijiazhuang",2171287,"石家庄","河北省",114.4666667,38.03333333,"12","14","11","94","2.49","982.05","2"
"wulumuqi",26198317,"乌鲁木齐","新疆维吾尔自治区",87.6,43.8,"12","23","34","52","9.99","1015.92","2"
"lanzhou",2145605,"兰州","甘肃省",103.8166667,36.05,"6","17","20","82","8","812.73","0"
"xining",2138941,"西宁","青海省",101.75,36.63333333,"3","21","32","63","9","745.01","0"
"xian",2157249,"西安","陕西省",108.9,34.26666667,"13","23","11","91","2.99","1017.9","0"
"yinchuan",2150551,"银川","宁夏回族自治区",106.2666667,38.33333333,"8","22","28","60","7","1016.8","0"
"zhengzhou",2172736,"郑州","河南省",113.7,34.8,"13","19","32","52","8","1015.92","0"
"jinan",2168327,"济南","山东省",117,36.63333333,"14","22","32","49",NA,"1017","0"
"taiyuan",2154547,"太原","山西省",112.5666667,37.86666667,"9","18","20","88","1.59","982.05","2"
"hefei",2127866,"合肥","安徽省",117.3,31.85,"17","23","34","60","9.99","1015.92","2"
"wuhan",2163866,"武汉","湖北省",114.35,30.61666667,"19","26","28","78","6","982.05","2"
"changsha",26198213,"长沙","湖南省",113,28.18333333,"21","28","28","65","9.99","982.05","2"
"nanjing",2137081,"南京","江苏省",118.8333333,32.03333333,"15","23","34","57","9.99","1015.92","2"
"chengdu",2158433,"成都","四川省",104.0833333,30.65,"19","27","20","69","4.01","1015.92","0"
"guiyang",2146703,"贵阳","贵州省",106.7,26.58333333,"18","26","28","73","9.99","1015.92","0"
"kunming",2160693,"昆明","云南省",102.6833333,25,"13","23","28","64","9.99","1015.92","2"
"nanning",2166473,"南宁","广西壮族自治区",108.3333333,22.8,"24","32","30","62","9.99","982.05","0"
"lasa",26198235,"拉萨","西藏自治区",91.16666667,29.66666667,"-1","15","30","50",NA,"643.41","0"
"hangzhou",2132574,"杭州","浙江省",120.15,30.23333333,"16","23","30","53","9.99","1015.92","0"
"nanchang",26198151,"南昌","江西省",115.8666667,28.68333333,"21","27","20","75","7","1016.4","0"
"guangzhou",2161838,"广州","广东省",113.25,23.13333333,"25","31","28","58","8","982.05","2"
"fuzhou",2139963,"福州","福建省",119.3,26.08333333,"21","29","28","65","9.99","982.05","0"
"taipei",2306179,"台北","台湾省",121.5166667,25.05,"24","28","28","70","9.99","982.05","0"
"haikou",2162779,"海口","海南省",110.3333333,20.03333333,"24","31","30","58","9.99","982.05","0"
"hongkong",24865698,"香港","香港特别行政区",114.1666667,22.3,"26","30","30","59","9.99","982.05","2"

数据一共有10列,字段解释:

  • en,城市英文名

  • woeid, Yahoo天气API定义的WOEID,用于匹配城市

  • zh,城市中文名

  • prov,城市所在省的中文名

  • long,经度(中国处于东经,不区别东经西经)

  • lat,纬度(中国处于北纬,不区别南纬北纬)

  • low,最低温度

  • high,最高温度

  • code,天气概括代码

  • humidity,湿度

  • visibility,能见度

  • pressure,大气压

  • rising,气压变动

这样数据就准备好了,那么接下来就是把天气数据对应到中国行政区地图上了。


3.3 中国地国加载

R语言通过第三方的地图R包,可以很方便的实现基于地图的可视化或基于地理信息的数据处理。那么R语言是如何做到的呢,是通过maps, mapdata, maptools这3个包合作完成的。

我们调用maptools包的readShapePoly()函数,加载中国行政区地图的数据信息,保存在map的变量中,直接用plot()函数就可以看到可视化的效果了。地图数据是我提前下载好的,保存放在mapdata目录中,一共全部3个文件bou2_4p.dbf,bou2_4p.shp和bou2_4p.shx。

> library(maps)
> library(mapdata)
> library(maptools)

> map<-readShapePoly('mapdata/bou2_4p.shp')     # 加载中国行政区地图数据
> plot(map)                                     # 画出中国行政区图


是不是很神奇,2行就画出是中国行政区地图的轮廓,我们再继续来分析map这个变量。先检查一下的map的类型,发现是sp包中定义的SpatialPolygonsDataFrame类型的。

> class(map)                                    # 查看map对象类型
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"

SpatialPolygonsDataFrame类型我们并不熟悉,再用pryr包的otype查检一下,面向对象系统的类型。

> library(pryr)
> otype(map)        # 发现是S4类型的data.frame
[1] "S4"

R语言基于S4的面向对象编程 http://blog.fens.me/r-class-s4/ 一文,我们已经掌握了S4类型的基础知识,在知道map是一个S4类型的实例后,大概就能猜出这个对象如何使用了。另外从命名上看,SpatialPolygonsDataFrame类型,应该是用data.frame存储了SpatialPolygons的类型的数据。 先通过length()函数和names()函数,从data.frame的角度查看一下map对象,包括7列925行。

> length(map)       # 一共有925条记录
[1] 925

> names(map)        # data.frame包括有7列
[1] "AREA"       "PERIMETER"  "BOU2_4M_"   "BOU2_4M_ID" "ADCODE93"
[6] "ADCODE99"   "NAME"

再通过str()函数查看map对象第一行数据的静态结构。

#省略

从这两个维度的观察,我们基本清楚map的结构,map里每一行是一个SpatialPolygonsDataFrame对象,包括5个属性,用于存储地图数据信息。取第一行数据data属性,查看结果,发现是黑龙江省的行政区地图数据。

> map[1,]@data
   AREA PERIMETER BOU2_4M_ BOU2_4M_ID ADCODE93 ADCODE99     NAME
0 54.447    68.489        2         23   230000   230000 黑龙江省

用第一行数据画图。

> plot(map[1,])


如果取前100行数据画图,那么应该是部分中国省的行政区地图了,果然如我所料。

> plot(map[1:100,])


由于本文并不是地图包的详细介绍,只要了解到map对象的基本使用就行了,稍后在博客中我会单独介绍用R做地图可视化的开发。


3.4 数据可视化

完成了地图数据加载后,再接下来就是数据可视化了。数据可视化,我认为要分成2部分操作,一部分是数据处理,另一部分是可视化输出。

我们先想一下要怎么进行数据处理,才能把天气数据和地图数据结合起来呢。我们的目标是要画出中国各省天气概况,会用到过之前过滤出的数据中code的数据,code的数据都是代码,我们还要定义code代码和实际意义的映射关系。

Yahoo的源数据中,一共定义了49种天气情况,如code.csv文件所示,根据描述我把相似的天气情况进行合并,最后保留18种天气概况特征。code代码映射文件为lablecode.csv。

code.csv文件。

#省略

字段解释:

  • code,源数据天气特征代码

  • en,英文描述

  • zh,中文描述

  • type,分类代码

lablecode.csv文件。

#省略

字段解释:

  • type,分类代码

  • alias,用于显示的别名

有了天气特征定义后,我们再把特征匹配到不同的颜色,并增加图例及文字描述,就生成了最终的中国各省天气概况的静态图片了。

#省略

运行程序,生成静态图片。

> data<-read.csv(file=filename(date),header=TRUE,fileEncoding="utf-8", encoding="utf-8")   # 定义数据源
> path=''                                                                                  # 定义输出路径
> summary(data,output=TRUE,path=path)      # 生成中国各省天气概况图
RStudioGD
       2


代码量大概100行左右,就可以生成这么复杂的天气和地图结合的图片,R真的很神奇!


3.5 可交互的静态图

这是锦上添花的一步,静态图片对于一般应用来说就够了。但如果图片还能动起来,是不是会更吸引人呢?我们可以尝试生成基于HTML5的、有动态效果的图,通过recharts包调Echarts库实现基于HTML5的动画,生成会动的可交互的图片。

由于recharts包没有发布的CRAN,我们需要用devtools包通过Github安装这个包。

> library(devtools)                     # 加载devtools
> install_github("taiyun/recharts")     # 下载安装recharts包
> library(recharts)                     # 加载recharts包

由于上面的天气概况是由离散值组成的,利用echarts的库,我们做一个连续值的可视化例子,比如白天气温和夜间气温。定义weather_html()函数,提供气温数据并调用recharts包,实现可视化的输出。

#省略

运行程序,以HTML输出中国各省白天气温。

> date<-as.Date('20141001',format='%Y%m%d')     # 设置日期
> data<-read.csv(file=filename(date),header=TRUE,fileEncoding="utf-8", encoding="utf-8")      # 加载数据
> path=''                                                                                     # 设置文件输出路径

> weather_html(data,type='high',output=FALSE,path='')           # 输出中国各省白天气温
[1] "气温"
[1] "chart path C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\RtmpqCHFPY"

程序会自动打开浏览器,呈现HTML的网页。


运行程序,以HTML输出中国各省夜间气温。在网页中,通过鼠标对地图进行交互,移动左下角的温度条,选择最高温度30,最低温度8.8,中国地图中由西南到东北变为灰色,说明这些地区的温度不在8.8到30度之间。当鼠标路过海南省的时候,海南省呈现黄色,并提示出温度为23度。

> weather_html(data,type='low', output=FALSE,path='')           # 中国各省夜间气温
[1] "气温"
[1] "chart path C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\RtmpqCHFPY"


如果不需要在浏览器中打开,只能想存储生成的网页,可以在程序中设置output为TRUE,当前目录下会生成20141001_night.html的文件。


作者介绍:

张丹,R语言中文社区专栏特邀作者,《R的极客理想》系列图书作者,民生银行大数据中心数据分析师,前况客创始人兼CTO。

10年IT编程背景,精通R ,Java, Nodejs 编程,获得10项SUN及IBM技术认证。丰富的互联网应用开发架构经验,金融大数据专家。个人博客 http://fens.me, Alexa全球排名70k。

著有《R的极客理想-工具篇》、《R的极客理想-高级开发篇》,合著《数据实践之美》,新书《R的极客理想-量化投资篇》(即将出版)。


《R的极客理想-工具篇》京东购买快速通道:https://item.jd.com/11524750.html

《R的极客理想-高级开发篇》京东购买快速通道:https://item.jd.com/11731967.html

《数据实践之美》京东购买快速通道:https://item.jd.com/12106224.html




微信回复关键字即可学习

回复 R              R语言快速入门免费视频 
回复 统计          统计方法及其在R中的实现
回复 用户画像   民生银行客户画像搭建与应用 
回复 大数据      大数据系列免费视频教程
回复 可视化      利用R语言做数据可视化
回复 数据挖掘   数据挖掘算法原理解释与应用
回复 机器学习   R&Python机器学习入门 

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

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