99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁(yè)精彩閱讀R語(yǔ)言天氣可視化應(yīng)用
R語(yǔ)言天氣可視化應(yīng)用
2017-05-07
收藏

R語(yǔ)言天氣可視化應(yīng)用

在很多人看來(lái),R語(yǔ)言還只是個(gè)玩具,完全不具備企業(yè)級(jí)應(yīng)用的能力。說(shuō)這些話的人,根本就不了解R語(yǔ)言,更不清楚如何做企業(yè)級(jí)應(yīng)用開(kāi)發(fā)。從我最早接觸R語(yǔ)言時(shí),就把R做為可視化引擎嵌入到了曬粉絲的微博應(yīng)用中;后來(lái)又開(kāi)發(fā)了數(shù)據(jù)挖掘算法競(jìng)賽網(wǎng)站,并把R語(yǔ)言做為算法引擎,并支持在線編程及運(yùn)行;我做的第三個(gè)R語(yǔ)言應(yīng)用就是本文要給大家分享的每日中國(guó)天氣微博應(yīng)用,這次同樣是把R做為可視化引擎,并讓R完成爬蟲(chóng)、XML文檔解析及數(shù)據(jù)處理等的任務(wù);當(dāng)然,我還實(shí)現(xiàn)了第四個(gè)、第五個(gè)、第六個(gè)以R為核心的應(yīng)用,都是量化投資方面的,會(huì)在下一本書(shū)《R的極客理想-量化投資篇》再介紹給大家。
從我的使用經(jīng)驗(yàn)來(lái)看,R語(yǔ)言已經(jīng)具備了企業(yè)級(jí)應(yīng)用的能力,但我并不是要用R語(yǔ)言完成所有編程任務(wù)。在我的項(xiàng)目環(huán)境中,大都是多種編程語(yǔ)言配合使用的,只有發(fā)揮各自語(yǔ)言的特性優(yōu)勢(shì),才是未來(lái)的發(fā)展方向。
本文所介紹的每日中國(guó)天氣微博應(yīng)用開(kāi)發(fā),將分為3篇介紹R語(yǔ)言和PHP語(yǔ)言的混合編程,第一篇為R語(yǔ)言功能實(shí)現(xiàn),第二篇為R包開(kāi)發(fā),第三篇為用PHP構(gòu)建微博應(yīng)用。本文是第一篇。
目錄
    項(xiàng)目介紹
    系統(tǒng)架構(gòu)設(shè)計(jì)
    R語(yǔ)言程序現(xiàn)實(shí)
1. 項(xiàng)目介紹
談到多語(yǔ)言混編,同如在計(jì)算機(jī)領(lǐng)域跨學(xué)科一樣,是我所一直倡導(dǎo)一種工作模式。當(dāng)編程語(yǔ)言百花齊放,各種細(xì)分市場(chǎng)的小眾語(yǔ)言如雨后春筍般地成長(zhǎng)起來(lái),比起通用型編程語(yǔ)言來(lái)說(shuō),這些小眾語(yǔ)言在特定的領(lǐng)域中有著非常明顯的優(yōu)勢(shì)。 比如統(tǒng)計(jì)應(yīng)用,如果用Java寫個(gè)邏輯回歸程序感覺(jué)深不見(jiàn)底,而用R語(yǔ)言實(shí)現(xiàn)邏輯回歸就是個(gè)很平常的一件事情。 再比如做一個(gè)Web網(wǎng)站,用PHP或Nodejs實(shí)現(xiàn)輕而易舉,如果用Java做不僅代碼量大,而且程序復(fù)雜。 所以,對(duì)于一個(gè)應(yīng)用來(lái)說(shuō),一種通用的語(yǔ)言并不一定是最好的解決方案,如果能實(shí)現(xiàn)多種語(yǔ)言的結(jié)合,那么你做出來(lái)的應(yīng)用可以很酷,很不一樣!
對(duì)于本文要介紹的 每日中國(guó)天氣 這個(gè)新浪微博應(yīng)用,就是一種多語(yǔ)言混編的實(shí)現(xiàn)。
項(xiàng)目介紹
這個(gè)項(xiàng)目的出發(fā)點(diǎn)很簡(jiǎn)單,就是通過(guò)可視化技術(shù),展示中國(guó)每個(gè)省份的天氣情況,給準(zhǔn)備旅游的朋友,提供一種出行的提示。
要做實(shí)現(xiàn)這個(gè)應(yīng)用,我們首先要列出,要實(shí)現(xiàn)哪些功能,會(huì)遇到哪些問(wèn)題等。
    天氣數(shù)據(jù):數(shù)據(jù)從哪里找到,如何下載,如何存儲(chǔ)。
    定時(shí)任務(wù):天氣數(shù)據(jù)需要每日更新,圖片需要每日新生成。
    地圖和天氣可視化:要把中國(guó)行政區(qū)圖和天氣數(shù)據(jù)結(jié)合在一起畫(huà)圖,讓用戶一眼就能看明白。
    Web展示:通過(guò)可視化技術(shù),我們生成的只是一張靜態(tài)圖片,如何發(fā)布到Web端進(jìn)行展示。
    微博:通過(guò)結(jié)合新浪微博,讓更多的用戶看到并使用這個(gè)應(yīng)用。
    用戶交互:用戶可以查看不同日期、不同類型的圖片,用戶還可以通過(guò)微博分享。
    雖然是個(gè)很小的應(yīng)用,但五臟俱全,我們也需要完整的思考,如何才能實(shí)現(xiàn)這個(gè)應(yīng)用呢!
2. 系統(tǒng)架構(gòu)設(shè)計(jì)
從上面的功能描述中,單獨(dú)使用一種語(yǔ)言也可以實(shí)現(xiàn)的。 如果單獨(dú)用PHP開(kāi)發(fā),做一個(gè)Web網(wǎng)站非常容易,連接新浪微博也有現(xiàn)成的SDK可以調(diào)用,爬取數(shù)據(jù)及存儲(chǔ)也不麻煩,那么如何實(shí)現(xiàn)地圖和天氣數(shù)據(jù)的可視化,似乎就是卡在這里了。 如果單獨(dú)用R開(kāi)發(fā),爬取數(shù)據(jù)及存儲(chǔ)同樣很容易實(shí)現(xiàn),地圖和天氣數(shù)據(jù)的可視化也是很方便就能畫(huà)出來(lái),但是用R做Web網(wǎng)站,那就會(huì)遇到很大的瓶頸了,因?yàn)镽是單線程同步的計(jì)算模型,Web應(yīng)用的高并發(fā)特點(diǎn),會(huì)直接讓R程序崩潰的。 所以,綜合上面的問(wèn)題,如果R語(yǔ)言和PHP語(yǔ)言能結(jié)合在一起使用,不僅能避開(kāi)每種語(yǔ)言不擅長(zhǎng)的地方,還能在擅長(zhǎng)的領(lǐng)域發(fā)揮出每種語(yǔ)言的特性,我們將通過(guò)多語(yǔ)言的混編技術(shù)做出很不一樣的應(yīng)用來(lái)。

為了實(shí)現(xiàn)應(yīng)用的功能需求,我們要設(shè)計(jì)一套系統(tǒng)架構(gòu)。

系統(tǒng)架構(gòu)解釋:

    通過(guò)定時(shí)器啟動(dòng)爬蟲(chóng)程序,到Y(jié)ahoo的天氣數(shù)據(jù)源下載數(shù)據(jù)。

    爬蟲(chóng)下載數(shù)據(jù)到本地服務(wù)器進(jìn)行解析,存儲(chǔ)應(yīng)用相關(guān)的數(shù)據(jù)到CSV文件。

    可視化程序,讀入天氣數(shù)據(jù)及地圖數(shù)據(jù),生成靜態(tài)的圖片作為可視化輸出。

    最終用戶通過(guò)新浪微博,加載Web應(yīng)用,看到了可視化生成的靜態(tài)圖片。

    最終用戶通過(guò)新浪微博分享了這個(gè)應(yīng)用,讓更多的人看到這個(gè)應(yīng)用。

下面按照語(yǔ)言的優(yōu)勢(shì),把應(yīng)用架構(gòu)以語(yǔ)言的特性來(lái)劃分,讓R語(yǔ)言實(shí)現(xiàn)爬蟲(chóng)、處理數(shù)據(jù)和可視化,讓PHP完成Web開(kāi)發(fā)、新浪API接入和用戶交互。

由于我們這個(gè)應(yīng)用,不需要讓R和PHP直接進(jìn)行通信,那么復(fù)雜度就會(huì)變得小很多了,像我之前做的曬粉絲應(yīng)用,是3種語(yǔ)言的結(jié)合包括了R, PHP, Java,通過(guò)Java實(shí)現(xiàn)中間程序的調(diào)度,讓R和PHP能夠?qū)崿F(xiàn)通信。

我們通過(guò)語(yǔ)言的劃分,就可以揚(yáng)長(zhǎng)避短,讓每種語(yǔ)言在最擅長(zhǎng)的領(lǐng)域,完成最擅長(zhǎng)的事情。

對(duì)于后臺(tái)技術(shù)應(yīng)用,定時(shí)器可以用Linux系統(tǒng)的CRON實(shí)現(xiàn);然后用R語(yǔ)言程序來(lái)爬取數(shù)據(jù),通過(guò)RCurl包來(lái)完成;爬取后的數(shù)據(jù)為XML格式,再通過(guò)R語(yǔ)言用XML包進(jìn)行解析,以CSV格式進(jìn)行本地存儲(chǔ);接下來(lái),再用R語(yǔ)言處理數(shù)據(jù),加載地圖包ggmap、mapdata、maptools,最后配合plot()函數(shù)實(shí)現(xiàn)圖片的輸出,保存在本地服務(wù)器上。

對(duì)于前端的PHP應(yīng)用來(lái)說(shuō),用PHP做一個(gè)Web網(wǎng)站很簡(jiǎn)單,使用YII快速開(kāi)發(fā)框架;用PHP的新浪微博SDK進(jìn)行API操作,實(shí)現(xiàn)新浪登陸,新浪分享等功能;最后Nginx + Spawn構(gòu)建出PHP運(yùn)行時(shí)環(huán)境,讓Nginx完成負(fù)載均衡和圖片加載,并配合PHP的訪問(wèn)規(guī)則,實(shí)現(xiàn)功能的切換。

合理的架構(gòu)設(shè)計(jì)加上適應(yīng)的語(yǔ)言的分工,就能輕松實(shí)現(xiàn)了 每日中國(guó)天氣 這樣的一個(gè)微博應(yīng)用。其實(shí),我們可以用這種多語(yǔ)言混搭的方式,創(chuàng)建出各種創(chuàng)新型的網(wǎng)站應(yīng)用,但前提是先能掌握多種語(yǔ)言。

這里我想再多說(shuō)一句,通常我認(rèn)識(shí)的程序員,都是在自己的技術(shù)領(lǐng)域中無(wú)限暢快,一旦他們掌握了一種語(yǔ)言的核心技術(shù),并有了一些開(kāi)發(fā)經(jīng)驗(yàn)后,往往不愿意再去學(xué)第二種語(yǔ)言。 對(duì)這些人來(lái)說(shuō),總覺(jué)得自己就是世界的中心,自己有能力實(shí)現(xiàn)的所有的功能。這些也都是有理想的程序員,只不過(guò)他們進(jìn)入了一個(gè)誤區(qū),被現(xiàn)有的技術(shù)給迷住了,看不到、也不愿意看到外面的世界已經(jīng)變了。我曾經(jīng)就是這樣的!

我承認(rèn)Java是一種無(wú)所不能的編程語(yǔ)言,但是如果你所有程序都用Java實(shí)現(xiàn),難道不覺(jué)得又費(fèi)時(shí)又費(fèi)力嗎?通用性越強(qiáng),反而專有領(lǐng)域的應(yīng)用性就越差。這也是我從Java單一的技術(shù)路線走出來(lái)的原因。其實(shí),在精通一門語(yǔ)言后,再去學(xué)習(xí)另外一門新的語(yǔ)言,就不是那么難了。但如果只是沉醉于已掌握的技術(shù),很快就會(huì)被一代新人,一代新工具所超越的。

3. R語(yǔ)言程序現(xiàn)實(shí)

下面就開(kāi)始介紹R語(yǔ)言的部分程序開(kāi)發(fā),在寫代碼之前,我們需要先梳理開(kāi)發(fā)流程,做一下程序設(shè)計(jì),R語(yǔ)言都需要實(shí)現(xiàn)哪些功能,用到哪些第三方R包。

我用一幅圖來(lái)說(shuō)明程序之間的調(diào)用關(guān)系,R語(yǔ)言的程序?qū)崿F(xiàn)一共包括了6個(gè)部分,爬蟲(chóng)程序、本地存儲(chǔ),地圖加載、數(shù)據(jù)可視化處理、生成靜態(tài)圖、生成可交互的靜態(tài)圖。

上圖中,分別標(biāo)出了每個(gè)步驟用的到R包或者功能函數(shù),同時(shí)我們可以按照這個(gè)流程來(lái)定義功能函數(shù),這樣我們就把整個(gè)應(yīng)用程序都規(guī)劃好,最后再對(duì)應(yīng)的寫代碼就不難了。


3.1 爬蟲(chóng)部分

對(duì)于爬蟲(chóng)部分來(lái)說(shuō),就是定時(shí)下載每個(gè)城市的或地區(qū)的天氣數(shù)據(jù),并解析數(shù)據(jù),只保留我們需要的字段,并以CSV的格式存儲(chǔ)?;ヂ?lián)網(wǎng)上有很多免費(fèi)公開(kāi)的天氣數(shù)據(jù)源,對(duì)我來(lái)說(shuō),最方便的數(shù)據(jù)源有2個(gè),一個(gè)是Yahoo的天氣數(shù)據(jù),另一個(gè)Google的天氣數(shù)據(jù),但由于Google的API從中國(guó)大陸會(huì)經(jīng)常會(huì)訪問(wèn)不到,所以我在這里選擇Yahoo的天氣數(shù)據(jù)源進(jìn)行訪問(wèn)。

yahoo天氣數(shù)據(jù)源的訪問(wèn)地址,如下所示。

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

其中WOEID代表城市對(duì)應(yīng)的代碼,如果想查看北京的天氣數(shù)據(jù),北京對(duì)應(yīng)的WOEID為2151330,可以訪問(wèn)用瀏覽器訪問(wèn) http://weather.yahooapis.com/forecastrss?w=2151330 。

我們通過(guò)瀏覽器打開(kāi)地址,就可以看到這個(gè)數(shù)據(jù),數(shù)據(jù)是以XML格式進(jìn)行發(fā)布的。

我們要解析這個(gè)XML文件,從中找到我們需要數(shù)據(jù)進(jìn)行提鄧。在R語(yǔ)言中,通過(guò)RCurl包實(shí)現(xiàn)HTTP的網(wǎng)絡(luò)訪問(wèn),抓取到整個(gè)的XML文檔數(shù)據(jù),然后通過(guò)XML包解析XML文檔的DOM樹(shù),就能找到我們需要的數(shù)據(jù)了。

本文的系統(tǒng)環(huán)境

    Win7 64bit

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

當(dāng)我們把業(yè)務(wù)邏輯和技術(shù)實(shí)現(xiàn)都想清楚了,就可以動(dòng)手寫代碼了,只十幾行代碼就能完成爬蟲(chóng)和XML文檔解析的功能。

> library(RCurl)        # 加載類庫(kù)
> library(XML)
>
> getWeather<-function (x){
+     url<-paste('http://weather.yahooapis.com/forecastrss?w=',x,'&u=c',sep="")       # yahoo的數(shù)據(jù)源地址
+     doc = xmlTreeParse(getURL(url),useInternal = TRUE)                              # 解析XML文檔
+
+     ans<-getNodeSet(doc, "http://yweather:atmosphere")
+     humidity<-as.numeric(sapply(ans, xmlGetAttr, "humidity"))                       # 溫度
+     visibility<-as.numeric(sapply(ans, xmlGetAttr, "visibility"))                   # 能見(jiàn)度
+     pressure<-as.numeric(sapply(ans, xmlGetAttr, "pressure"))                       # 氣壓
+     rising<-as.numeric(sapply(ans, xmlGetAttr, "rising"))                           # 氣壓變動(dòng)
+
+     ans<-getNodeSet(doc, "http://item/yweather:condition")
+     code<-sapply(ans, xmlGetAttr, "code")                                           # 天氣情況
+
+     ans<-getNodeSet(doc, "http://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格式返回
+ }

運(yùn)行程序,查看返回結(jié)果。

> w<-getWeather(2151330)    # 執(zhí)行爬蟲(chóng)程序
[1] "2151330 ==> 9 13 21 59 4.1 1016.4 0"

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

對(duì)于功能需求來(lái)說(shuō),一個(gè)城市只保存7個(gè)字段就行了,其他的XML文檔的數(shù)據(jù)可以全部過(guò)濾掉不管。


3.2 本地存儲(chǔ)

我們通過(guò)爬蟲(chóng)下載并過(guò)濾后的數(shù)據(jù),已經(jīng)是data.frame的格式了,通過(guò)write.csv()函數(shù)就把這些數(shù)據(jù)輸出到本地文件系統(tǒng)中保存起來(lái),做為數(shù)據(jù)的備份。

我們?cè)谔幚肀镜卮鎯?chǔ)的過(guò)程中,除了要生成一個(gè)CSV文件,還包括了 文件命名,把多個(gè)城市的數(shù)據(jù)合并到一個(gè)文件存儲(chǔ)的問(wèn)題。下面我們需要再定義兩個(gè)函數(shù),filename()函數(shù)用于新生成文件的命名,loadDate()函數(shù)用于多個(gè)城市數(shù)據(jù)的加載,合并在一個(gè)文件中保存。

城市列表應(yīng)該是我們需要提單準(zhǔn)備好的,我這里只選取了中國(guó)的34個(gè)城市作為我們要獲得的城市天氣數(shù)據(jù)的信息。如果想爬取更多的城市天氣數(shù)據(jù)的信息,那么補(bǔ)充這個(gè)列表就行了。

城市列表數(shù)據(jù)文件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,長(zhǎng)春,吉林省,125.3166667,43.86666667
shenyang,2148332,沈陽(yáng),遼寧省,123.4,41.83333333
hohhot,2149760,呼和浩特,內(nèi)蒙古自治區(qū),111.8,40.81666667
shijiazhuang,2171287,石家莊,河北省,114.4666667,38.03333333
wulumuqi,26198317,烏魯木齊,新疆維吾爾自治區(qū),87.6,43.8
lanzhou,2145605,蘭州,甘肅省,103.8166667,36.05
xining,2138941,西寧,青海省,101.75,36.63333333
xian,2157249,西安,陜西省,108.9,34.26666667
yinchuan,2150551,銀川,寧夏回族自治區(qū),106.2666667,38.33333333
zhengzhou,2172736,鄭州,河南省,113.7,34.8
jinan,2168327,濟(jì)南,山東省,117,36.63333333
taiyuan,2154547,太原,山西省,112.5666667,37.86666667
hefei,2127866,合肥,安徽省,117.3,31.85
wuhan,2163866,武漢,湖北省,114.35,30.61666667
changsha,26198213,長(zhǎng)沙,湖南省,113,28.18333333
nanjing,2137081,南京,江蘇省,118.8333333,32.03333333
chengdu,2158433,成都,四川省,104.0833333,30.65
guiyang,2146703,貴陽(yáng),貴州省,106.7,26.58333333
kunming,2160693,昆明,云南省,102.6833333,25
nanning,2166473,南寧,廣西壯族自治區(qū),108.3333333,22.8
lasa,26198235,拉薩,西藏自治區(qū),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,臺(tái)北,臺(tái)灣省,121.5166667,25.05
haikou,2162779,???海南省,110.3333333,20.03333333
hongkong,24865698,香港,香港特別行政區(qū),114.1666667,22.3
macau,20070017,澳門,澳門特別行政區(qū),113.5,22.2

字段解釋:

    第一列,城市的英文名

    第二列,WOEID代碼

    第三列,城市的中文名

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

    第五列,經(jīng)度(默認(rèn)為東經(jīng))

    第六列,緯度(默認(rèn)為北緯)

用于生成數(shù)據(jù)文件的R語(yǔ)言的函數(shù)實(shí)現(xiàn)。

> filename<-function(date=Sys.time()){            # 文件根據(jù)日期來(lái)命名
+     paste(format(date, "%Y%m%d"),".csv",sep="")
+ }

> loadDate<-function(date){                       # 讀取城市列表,調(diào)用爬蟲(chóng)函數(shù),合并數(shù)據(jù)保存到一個(gè)文件中。
+     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")
+ }

運(yùn)行程序loadDate()的函數(shù),程序會(huì)根據(jù)城市列表的數(shù)據(jù),調(diào)用getWeather()函數(shù)自動(dòng)爬取我們定義的所有城市的天氣數(shù)據(jù)。

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

> loadDate(date)                    # 爬取數(shù)據(jù)
[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"

程序運(yùn)行完成后,會(huì)在當(dāng)前目錄生成一個(gè)名字為20141001.csv文件。打開(kāi)20141001.csv文件,這個(gè)文件就是接下來(lái)用于生成可視化圖片的基礎(chǔ)數(shù)據(jù)了。

"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,"長(zhǎng)春","吉林省",125.3166667,43.86666667,"3","6","11","81","9.99","1015.92","1"
"shenyang",2148332,"沈陽(yáng)","遼寧省",123.4,41.83333333,"7","16","34","27","9.99","1015.92","0"
"hohhot",2149760,"呼和浩特","內(nèi)蒙古自治區(qū)",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,"烏魯木齊","新疆維吾爾自治區(qū)",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,"銀川","寧夏回族自治區(qū)",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,"濟(jì)南","山東省",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,"長(zhǎng)沙","湖南省",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,"貴陽(yáng)","貴州省",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,"南寧","廣西壯族自治區(qū)",108.3333333,22.8,"24","32","30","62","9.99","982.05","0"
"lasa",26198235,"拉薩","西藏自治區(qū)",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,"臺(tái)北","臺(tái)灣省",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,"香港","香港特別行政區(qū)",114.1666667,22.3,"26","30","30","59","9.99","982.05","2"

數(shù)據(jù)一共有10列,字段解釋:

    en,城市英文名

    woeid, Yahoo天氣API定義的WOEID,用于匹配城市

    zh,城市中文名

    prov,城市所在省的中文名

    long,經(jīng)度(中國(guó)處于東經(jīng),不區(qū)別東經(jīng)西經(jīng))

    lat,緯度(中國(guó)處于北緯,不區(qū)別南緯北緯)

    low,最低溫度

    high,最高溫度

    code,天氣概括代碼

    humidity,濕度

    visibility,能見(jiàn)度

    pressure,大氣壓

    rising,氣壓變動(dòng)

這樣數(shù)據(jù)就準(zhǔn)備好了,那么接下來(lái)就是把天氣數(shù)據(jù)對(duì)應(yīng)到中國(guó)行政區(qū)地圖上了。


3.3 中國(guó)地國(guó)加載

R語(yǔ)言通過(guò)第三方的地圖R包,可以很方便的實(shí)現(xiàn)基于地圖的可視化或基于地理信息的數(shù)據(jù)處理。那么R語(yǔ)言是如何做到的呢,是通過(guò)maps, mapdata, maptools這3個(gè)包合作完成的。

我們調(diào)用maptools包的readShapePoly()函數(shù),加載中國(guó)行政區(qū)地圖的數(shù)據(jù)信息,保存在map的變量中,直接用plot()函數(shù)就可以看到可視化的效果了。地圖數(shù)據(jù)是我提前下載好的,保存放在mapdata目錄中,一共全部3個(gè)文件bou2_4p.dbf,bou2_4p.shp和bou2_4p.shx。

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

> map<-readShapePoly('mapdata/bou2_4p.shp')     # 加載中國(guó)行政區(qū)地圖數(shù)據(jù)
> plot(map)                                     # 畫(huà)出中國(guó)行政區(qū)圖

是不是很神奇,2行就畫(huà)出是中國(guó)行政區(qū)地圖的輪廓,我們?cè)倮^續(xù)來(lái)分析map這個(gè)變量。先檢查一下的map的類型,發(fā)現(xiàn)是sp包中定義的SpatialPolygonsDataFrame類型的。

> class(map)                                    # 查看map對(duì)象類型
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"

SpatialPolygonsDataFrame類型我們并不熟悉,再用pryr包的otype查檢一下,面向?qū)ο笙到y(tǒng)的類型。

> library(pryr)
> otype(map)        # 發(fā)現(xiàn)是S4類型的data.frame
[1] "S4"

R語(yǔ)言基于S4的面向?qū)ο缶幊?http://blog.fens.me/r-class-s4/ 一文,我們已經(jīng)掌握了S4類型的基礎(chǔ)知識(shí),在知道m(xù)ap是一個(gè)S4類型的實(shí)例后,大概就能猜出這個(gè)對(duì)象如何使用了。另外從命名上看,SpatialPolygonsDataFrame類型,應(yīng)該是用data.frame存儲(chǔ)了SpatialPolygons的類型的數(shù)據(jù)。 先通過(guò)length()函數(shù)和names()函數(shù),從data.frame的角度查看一下map對(duì)象,包括7列925行。

> length(map)       # 一共有925條記錄
[1] 925

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

再通過(guò)str()函數(shù)查看map對(duì)象第一行數(shù)據(jù)的靜態(tài)結(jié)構(gòu)。

#省略

從這兩個(gè)維度的觀察,我們基本清楚map的結(jié)構(gòu),map里每一行是一個(gè)SpatialPolygonsDataFrame對(duì)象,包括5個(gè)屬性,用于存儲(chǔ)地圖數(shù)據(jù)信息。取第一行數(shù)據(jù)data屬性,查看結(jié)果,發(fā)現(xiàn)是黑龍江省的行政區(qū)地圖數(shù)據(jù)。

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

用第一行數(shù)據(jù)畫(huà)圖。

> plot(map[1,])

如果取前100行數(shù)據(jù)畫(huà)圖,那么應(yīng)該是部分中國(guó)省的行政區(qū)地圖了,果然如我所料。

> plot(map[1:100,])

由于本文并不是地圖包的詳細(xì)介紹,只要了解到map對(duì)象的基本使用就行了,稍后在博客中我會(huì)單獨(dú)介紹用R做地圖可視化的開(kāi)發(fā)。

3.4 數(shù)據(jù)可視化

完成了地圖數(shù)據(jù)加載后,再接下來(lái)就是數(shù)據(jù)可視化了。數(shù)據(jù)可視化,我認(rèn)為要分成2部分操作,一部分是數(shù)據(jù)處理,另一部分是可視化輸出。

我們先想一下要怎么進(jìn)行數(shù)據(jù)處理,才能把天氣數(shù)據(jù)和地圖數(shù)據(jù)結(jié)合起來(lái)呢。我們的目標(biāo)是要畫(huà)出中國(guó)各省天氣概況,會(huì)用到過(guò)之前過(guò)濾出的數(shù)據(jù)中code的數(shù)據(jù),code的數(shù)據(jù)都是代碼,我們還要定義code代碼和實(shí)際意義的映射關(guān)系。

Yahoo的源數(shù)據(jù)中,一共定義了49種天氣情況,如code.csv文件所示,根據(jù)描述我把相似的天氣情況進(jìn)行合并,最后保留18種天氣概況特征。code代碼映射文件為lablecode.csv。

code.csv文件。

#省略

字段解釋:

    code,源數(shù)據(jù)天氣特征代碼

    en,英文描述

    zh,中文描述

    type,分類代碼

lablecode.csv文件。

#省略

字段解釋:

    type,分類代碼

    alias,用于顯示的別名

有了天氣特征定義后,我們?cè)侔?a href='/map/tezheng/' style='color:#000;font-size:inherit;'>特征匹配到不同的顏色,并增加圖例及文字描述,就生成了最終的中國(guó)各省天氣概況的靜態(tài)圖片了。

#省略

運(yùn)行程序,生成靜態(tài)圖片。

> data<-read.csv(file=filename(date),header=TRUE,fileEncoding="utf-8", encoding="utf-8")   # 定義數(shù)據(jù)源
> path=''                                                                                  # 定義輸出路徑
> summary(data,output=TRUE,path=path)      # 生成中國(guó)各省天氣概況圖
RStudioGD
        2

代碼量大概100行左右,就可以生成這么復(fù)雜的天氣和地圖結(jié)合的圖片,R真的很神奇!
3.5 可交互的靜態(tài)圖

這是錦上添花的一步,靜態(tài)圖片對(duì)于一般應(yīng)用來(lái)說(shuō)就夠了。但如果圖片還能動(dòng)起來(lái),是不是會(huì)更吸引人呢?我們可以嘗試生成基于HTML5的、有動(dòng)態(tài)效果的圖,通過(guò)recharts包調(diào)Echarts庫(kù)實(shí)現(xiàn)基于HTML5的動(dòng)畫(huà),生成會(huì)動(dòng)的可交互的圖片。

由于recharts包沒(méi)有發(fā)布的CRAN,我們需要用devtools包通過(guò)Github安裝這個(gè)包。

> library(devtools)                     # 加載devtools
> install_github("taiyun/recharts")     # 下載安裝recharts
> library(recharts)                     # 加載recharts

由于上面的天氣概況是由離散值組成的,利用echarts的庫(kù),我們做一個(gè)連續(xù)值的可視化例子,比如白天氣溫和夜間氣溫。定義weather_html()函數(shù),提供氣溫?cái)?shù)據(jù)并調(diào)用recharts包,實(shí)現(xiàn)可視化的輸出。

#省略

運(yùn)行程序,以HTML輸出中國(guó)各省白天氣溫。

> date<-as.Date('20141001',format='%Y%m%d')     # 設(shè)置日期
> data<-read.csv(file=filename(date),header=TRUE,fileEncoding="utf-8", encoding="utf-8")      # 加載數(shù)據(jù)
> path=''                                                                                     # 設(shè)置文件輸出路徑

> weather_html(data,type='high',output=FALSE,path='')           # 輸出中國(guó)各省白天氣溫
[1] "氣溫"
[1] "chart path C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\RtmpqCHFPY"

程序會(huì)自動(dòng)打開(kāi)瀏覽器,呈現(xiàn)HTML的網(wǎng)頁(yè)。

運(yùn)行程序,以HTML輸出中國(guó)各省夜間氣溫。在網(wǎng)頁(yè)中,通過(guò)鼠標(biāo)對(duì)地圖進(jìn)行交互,移動(dòng)左下角的溫度條,選擇最高溫度30,最低溫度8.8,中國(guó)地圖中由西南到東北變?yōu)榛疑?,說(shuō)明這些地區(qū)的溫度不在8.8到30度之間。當(dāng)鼠標(biāo)路過(guò)海南省的時(shí)候,海南省呈現(xiàn)黃色,并提示出溫度為23度。
> weather_html(data,type='low', output=FALSE,path='')           # 中國(guó)各省夜間氣溫
[1] "氣溫"
[1] "chart path C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\RtmpqCHFPY"

如果不需要在瀏覽器中打開(kāi),只能想存儲(chǔ)生成的網(wǎng)頁(yè),可以在程序中設(shè)置output為TRUE,當(dāng)前目錄下會(huì)生成20141001_night.html的文件。

數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼

若不方便掃碼,搜微信號(hào):CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說(shuō)明請(qǐng)參見(jiàn):http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }