北京氣溫咋樣 - Python,數據繪圖,matplotlib

matplotlib 是最流行的 python 繪圖包之一,相比起之前給大家介紹的小清新 pygal,matplotlib 顯得比較偏理工。具體安裝使用請參考官方文檔。今天小狼要給大家舉的栗子很簡單:繪制一個折線圖看看帝都的氣溫變化情況。源碼請移步小狼 GitHub 下的 bj_tmp_matplotlib 文件夾。

巧婦難為無米之炊,第一步就是找數據。這里我們使用的天氣數據來自于 Weather Underground。無需注冊你就可以下載有記錄的年份的全球各地天氣數據,如果注冊的話則可以得到一個 API,你也可以利用 API 來獲取數據。我們需要獲取北京 2016 年全年的氣溫數據,以此來繪制全年的高低氣溫走勢圖。該網站的數據顯示非常清晰友好,由于我們需要的數據也不多,直接轉存成 .csv 格式備用。

接下來開寫代碼,首先導入一些我們要用到的包,用來支持 .csv 文件處理和時間數據處理:

import csv
import matplotlib.dates
from datetime import datetime
from matplotlib import pyplot as plt

寫一個函數來把時間數據存儲到列表里,并且轉換成可被 python 理解的時間格式:

def date_to_list(data_index):
    """ save date to a list """
    results = []
    for row in data:
        results.append(datetime.strptime(row[data_index], '%Y-%m-%d'))
    return results

再來一個函數用來存儲氣溫數據:

def data_to_list(data_index):
    """ save data to a list """
    results = []
    for row in data:
        results.append(int(row[data_index]))
    return results

現在看一下那個 .csv 文件的構造和內容:

filename = 'beijing_2016.csv'
with open(filename) as bj:
    data = csv.reader(bj)
    header = next(data)

    print(header)
    print(next(data))

通過兩個 print 語句我們得到如下結果:

['date_akdt', 'high_temp_f', 'avg_temp_f', 'low_temp_f', 'high_dew_point_f', 'avg_dew_point_f', 'low_dew_point_f', 'high_humidity_pct', 'avg_humidity_pct', 'low_humidity_pct', 'high_sea_level_press_in', 'avg_sea_level_press_in', 'low_sea_level_press_in', 'high_visibility_mi', 'avg_visibility_mi', 'low_visibility_mi', 'high_wind_mph', 'avg_wind_mph', 'high_wind_mph', 'sum_precip_in', 'events']
['2016-01-01', '41', '30', '19', '23', '18', '14', '86', '68', '25', '30.36', '30.23', '30.12', '4', '3', '1', '9', '3', '-', '0', '']

上面的輸出分別是表頭和第一行數據的內容,我們可以看到其中有我們需要的時間,最高溫度和最低溫度,分別對應的 index 是 0,1,3。當然,你也可以直接用代碼獲取 index,尤其是當數據類型非常多的時候:

    print('date_akdt', header.index('date_akdt'))
    print('high_temp_f', header.index('high_temp_f'))
    print('low_temp_f', header.index('low_temp_f'))

獲得輸出:

date_akdt 0
high_temp_f 1
low_temp_f 3

知道數據位置后,我們就可以單獨提取這些數據存到列表里,用于之后的繪圖。這里有個坑,因為我們讀取 .csv 文件的時候用到了迭代器,所以我們需要先轉存一下數據,否則僅能返回第一條數據,其余的則返回空值。

    data = list(data)

接下來就是把數據存到列表里,由于獲取的溫度是華氏度,所以溫度這里加了一個轉換過程 (x-32)/1.8

    high_temp_f_bj = data_to_list(1)
    high_temp_c_bj = [int((x-32)/1.8) for x in high_temp_f_bj]

    low_temp_f_bj = data_to_list(3)
    low_temp_c_bj = [int((x-32)/1.8) for x in low_temp_f_bj]

    date = date_to_list(0)

然后就到了繪圖步驟,先繪制高溫曲線看一下:

    plt.plot(date, high_temp_c_bj)
    plt.show()

我們得到一個醬紫的圖,不錯哦:

bj_temp_2016_high.png

把低溫曲線也加進去:

    plt.plot(date, low_temp_c_bj)
bj_temp_2016.png

做一些顯示上的優化(咋就這么這么這么麻煩呢!):

    plt.figure(figsize=(15, 5), dpi=100)
    plt.plot(date, high_temp_c_bj, c='xkcd:orange')
    plt.plot(date, low_temp_c_bj,c='xkcd:azure')

    plt.title('Beijing Temperatures (High & Low) - Year 2016', fontsize=22)
    plt.ylabel('Temperature (C)', fontsize=20)
    plt.tick_params(axis='both', labelsize=16)
    plt.fill_between(date, high_temp_c_bj, low_temp_c_bj, facecolor='xkcd:tan', alpha=0.2)

    plt.gca().xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%Y-%m"))
    plt.gcf().autofmt_xdate()
    plt.margins(x=0,y=0.2)

    plt.show()

上面的代碼中,figure() 可調整繪圖大小和分辨率,fill_between() 可在兩條折線中間繪制填充色,autofmt_xdate() 可將橫坐標斜著顯示以避免重疊,margins() 可設置坐標軸和邊框的留白距離。

bj_temp_2016_final.png

至此,總算是差不多了。其實用 matplotlib 繪制類似這樣的圖是比較基礎的,但是我們可以看到稍有不慎在數據處理上還是有坑的,包括最后的 x 軸坐標調整也費了小狼一些時間去研究,幸好過程中得到幾位大牛的指(教)點(訓)。此外,在寫提取數據的代碼時,如果對數據質量沒有把握,還是最好加入 try - except - else 模塊方為妥當。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容