文檔內容:
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()
運行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()
三:對氣象數據進行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()
測試上面代碼:在命令行運行 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)
測試上面代碼:在命令行運行 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)
測試上面代碼:在命令行運行 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)
測試上面代碼:在命令行運行 reader.py | mapper.py | reducer.py | drawer.py,查看輸出。
顯示效果如下圖:(注:在前面處理的數據中, 可能由於采樣的錯誤,會有出現999.9度的最高溫度, 顯然不符常理。在本例中,沒有對此種錯誤進行深究,一致將超度50度的溫度處理成50度)
四 說明
1. 本例中,其實第二步 對下載的氣象數據歸檔整理並讀取數據 是多余的, 可以直接在第一步中修改文件存儲目錄跳過第二步。但為了熟悉python對文件的操作,還是將第二步的代碼保留了下來。
2. 本例中,代碼能運行得到實驗目標,但並為對代碼進行優化。請讀者根據需要自行更改。
3. python代碼的一大特點就是看起來像偽代碼,又本例python代碼比較簡單,故沒有給出注釋。