基於python的《Hadoop權威指南》一書中氣象數據下載和map reduce化數據處理及其可視化


 

文檔內容:

  1:下載《hadoop權威指南》中的氣象數據

  2:對下載的氣象數據歸檔整理並讀取數據

  3:對氣象數據進行map reduce進行處理

關鍵詞:《Hadoop權威指南》氣象數據  map reduce  python  matplotlib可視化

 

一:下載《hadoop權威指南》一書中的氣象數據

  《hadoop權威指南》一書中的氣象數據位於 http://ftp3.ncdc.noaa.gov/pub/data/noaa/

  新建 getdata.py文件, 並加入如下代碼:

 1 #http://my.oschina.net/chyileon/blog/134915
 2 import urllib
 3 import urllib2
 4 from bs4 import BeautifulSoup
 5 import re
 6 import os
 7 import shutil
 8 
 9 def getdata():
10     year = 1901
11     endYear = 1921
12     urlHead = 'http://ftp3.ncdc.noaa.gov/pub/data/noaa/'
13 
14     while year < endYear:
15         if os.path.isdir(str(year)):
16             shutil.rmtree(str(year))
17         os.mkdir(str(year))
18 
19         page = urllib2.urlopen(urlHead+str(year))
20         soup = BeautifulSoup(page, from_encoding="gb18030")
21 
22         for link in soup.findAll('a'):
23             if link.getText().find('.gz') != -1:
24                 filename = link.getText()
25 
26                 urllib.urlretrieve(urlHead+str(year)+'/'+filename, str(year)+'/'+filename)
27 
28         year += 1
29 
30 def main():
31     getdata()
32 
33 if __name__=="__main__":
34     main()
View Code

  運行getdata.py,將在當前目錄下生成數據文件

 

二:對下載的氣象數據歸檔整理並讀取數據

  說明:上一步驟在當前目錄下生成【1901】~【1921】 共20文件,文件里是壓縮的氣象數據,本步驟知識將數據移動data文件夾下 

  新建 movedata.py文件, 並加入如下代碼:

 1 import os
 2 import shutil
 3 
 4 def movedata():
 5 
 6     curpath = os.getcwd()
 7     list = os.listdir(curpath)
 8     datapath = os.path.join(curpath, "data")
 9     print(datapath)
10     for line in list:
11         filepath = os.path.join(curpath, line)
12         if os.path.isdir(filepath):
13             shutil.move(filepath,datapath)
14 
15 def main():
16     movedata()
17 
18 if __name__=="__main__":
19     main()
View Code

 

三:對氣象數據進行map reduce進行處理

  說明:這里要讀取文件中的數據內容,並通過將數據map reduce 化獲取每年的最高、低溫度

 

  1: 將文件中的數據內容逐行讀出

    新建reader.py文件,並加入如下代碼:

 1 import os
 2 import gzip
 3 
 4 def reader():
 5 
 6     curpath = os.getcwd()
 7     datapath = os.path.join(curpath, r"data")
 8 
 9     for yearlist in os.listdir(datapath):
10         oneyearpath = os.path.join(datapath, yearlist)
11         datalist = os.listdir(oneyearpath)
12         for line in datalist:
13             onedatapath = os.path.join(oneyearpath, line)
14             with gzip.open(onedatapath, 'rb') as pf:
15                 print (pf.read())
16 
17 def main():
18     reader()
19 
20 if __name__=="__main__":
21     main()
View Code

    測試上面代碼:在命令行運行 reader.py,查看輸出

  2:通過mapper方法把數據處理成 "year \n temperature"的輸出形式,如 "1901  242",其中 242 表示溫度為24.2度

   新建mapper.py文件,並加入如下代碼: 

 1 import sys
 2 
 3 def mapper(inlist):
 4     for line in inlist:
 5         if len(line) > 92:
 6             year = (line[15:19])
 7             if line[87] == '+':
 8                 temperataure = line[88:92]
 9             else:
10                 temperataure = line[87:92]
11             print year, temperataure
12 
13 def main(inlist):
14     mapper(inlist)
15 
16 if __name__=="__main__":
17     inlist = []
18     for line in sys.stdin:
19         inlist.append(line)
20     main(inlist)
View Code

  測試上面代碼:在命令行運行  reader.py | mapper.py ,查看輸出。(注:這是是利用管道,把reader.py的輸出作為mapper.py的輸入)

  3:通過reducer方法將mapper的輸出數據整理並計算每年的最高、低溫度,並輸出

   新建reducer.py文件,並加入如下代碼:

 1 import sys
 2 
 3 def reducer(inlist):
 4     cur_year = None
 5     maxtemp = None
 6     mintemp = None
 7     for line in inlist:
 8         year, temp = line.split()
 9         try:
10             temp = int(temp)
11         except ValueError:
12             continue
13         if cur_year == year:
14             if temp > maxtemp:
15                 maxtemp = temp
16             if temp < mintemp:
17                 mintemp = temp
18         else:
19             if cur_year != None:
20                 print cur_year, maxtemp, mintemp
21             cur_year = year
22             maxtemp = temp
23             mintemp = temp
24     print cur_year, maxtemp, mintemp
25 
26 def main(inlist):
27     reducer(inlist)
28 
29 if __name__=="__main__":
30     inlist = []
31     for line in sys.stdin:
32         inlist.append(line)
33     main(inlist)
View Code

  測試上面代碼:在命令行運行  reader.py | mapper.py | reducer.py,查看輸出。

  4:使用matplotlib對每年的最高、低數據進行可視化

    新建drawer.py文件,並加入如下代碼:

 1 import sys
 2 import matplotlib.pyplot as plt
 3 
 4 def drawer(inlist):
 5     yearlist = []
 6     maxtemplist = []
 7     mintemplist = []
 8     for line in inlist:
 9         year, maxtemp, mintemp = line.split()
10         try:
11             year = int(year)
12             maxtemp = int(maxtemp) / 10.
13             if(maxtemp) > 50:
14                 maxtemp = 50
15             mintemp = int(mintemp) / 10.
16         except ValueError:
17             continue
18         yearlist.append(year)
19         maxtemplist.append(maxtemp)
20         mintemplist.append(mintemp)
21     plt.plot(yearlist, maxtemplist, 'bd--')
22     plt.plot(yearlist, mintemplist, 'rp:')
23     plt.xlim(1901, 1920)
24     plt.ylim(-60, 80)
25     plt.title('min-max temperature for 1901-1920')
26     plt.xlabel('year')
27     plt.ylabel('temperature')
28     plt.legend(('max temp','min temp'), loc='upper right')
29     plt.show()
30     print(yearlist, maxtemplist, mintemplist)
31 
32 def main(inlist):
33     drawer(inlist)
34 
35 if __name__=="__main__":
36     inlist = []
37     for line in sys.stdin:
38         inlist.append(line)
39     main(inlist)
View Code

  測試上面代碼:在命令行運行  reader.py | mapper.py | reducer.py | drawer.py,查看輸出。

  顯示效果如下圖:(注:在前面處理的數據中, 可能由於采樣的錯誤,會有出現999.9度的最高溫度, 顯然不符常理。在本例中,沒有對此種錯誤進行深究,一致將超度50度的溫度處理成50度)

  

 

四 說明

  1. 本例中,其實第二步 對下載的氣象數據歸檔整理並讀取數據 是多余的, 可以直接在第一步中修改文件存儲目錄跳過第二步。但為了熟悉python對文件的操作,還是將第二步的代碼保留了下來。

  2. 本例中,代碼能運行得到實驗目標,但並為對代碼進行優化。請讀者根據需要自行更改。

  3. python代碼的一大特點就是看起來像偽代碼,又本例python代碼比較簡單,故沒有給出注釋。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM