往期回顧 從零開始學(xué)Python【17】--matplotlib(面積圖)
從零開始學(xué)Python【16】--matplotlib(雷達(dá)圖)
從零開始學(xué)Python【15】--matplotlib(散點(diǎn)圖)
從零開始學(xué)Python【14】--matplotlib(折線圖)
從零開始學(xué)Python【13】--matplotlib(直方圖)
從零開始學(xué)Python【12】--matplotlib(箱線圖)
從零開始學(xué)Python【11】--matplotlib(餅圖)
從零開始學(xué)Python【10】--matplotlib(條形圖) 前言
新講開始啦~今天我們帶給大家?guī)淼氖顷P(guān)于如何繪制填充表格熱力圖的知識(shí)點(diǎn),先給大家看一下效果圖。 從效果圖里我們可以發(fā)現(xiàn),所謂的填充表格熱力圖就是將原本為數(shù)字表(數(shù)組)的單元格以顏色來填充,顏色的深淺表示數(shù)值的大小。我想,對(duì)于這樣的圖來說,總比直接看密密麻麻的數(shù)值表要輕松的多吧,畢竟顏色感官比數(shù)字感官要直接,要具有更強(qiáng)的沖擊。除了填充表格熱力圖,還有更為常見的地圖熱力圖等。那填充表格熱力圖是如何應(yīng)用Python來實(shí)現(xiàn)的呢?就讓我們手把手的進(jìn)行講解吧~
數(shù)據(jù)采集—?dú)鉁財(cái)?shù)據(jù)
在繪圖之前,需要說明一下繪圖的數(shù)據(jù)源,案例中的數(shù)據(jù)是通過爬蟲獲取的,用的是上海9月份每天的最高氣溫,即生成兩列數(shù)據(jù)(日期和最高氣溫)。在有了原始數(shù)據(jù)的基礎(chǔ)上,還需要對(duì)數(shù)據(jù)進(jìn)行清洗和整理,關(guān)于這部分是做任何數(shù)據(jù)分析或可視化都必經(jīng)的坎。詳細(xì)可以通過下面的代碼來了解: # ========== Python3 + Jupyter ========== # # 導(dǎo)入所需的第三方包 import datetime import calendar import requests from bs4 import BeautifulSoup import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns
# 采集數(shù)據(jù) # 上海2017年9月份歷史氣溫?cái)?shù)據(jù) url = 'http://lishi.tianqi.com/shanghai/201709.html'
# 發(fā)送爬蟲請求 response = requests.get(url).text # 解析源代碼 soup = BeautifulSoup(response, 'html.parser') # 根據(jù)HTML標(biāo)記語言,查詢目標(biāo)標(biāo)記下的數(shù)據(jù) datas = soup.findAll('div',{'class':'tqtongji2'})[0].findAll('ul')[1:]
# 抓取日期數(shù)據(jù) date = [i.findAll('li')[0].text for i in datas] # 抓取最高溫?cái)?shù)據(jù) high = [i.findAll('li')[1].text for i in datas]
# 創(chuàng)建數(shù)據(jù)框 df = pd.DataFrame({'date':date, 'high':high}) # 變量類型 df.dtypes
# 將date變量轉(zhuǎn)換為日期類型 df.date = pd.to_datetime(df.date) # 將high變量轉(zhuǎn)換成數(shù)值型 df.high = df.high.astype('int')
# 數(shù)據(jù)處理 # 由日期型數(shù)據(jù)衍生出weekday df['weekday'] = df.date.apply(pd.datetime.weekday)
# 由日期型數(shù)據(jù)計(jì)算week_of_month,即當(dāng)前日期在本月中是第幾周 # 由于沒有現(xiàn)成的函數(shù),這里自定義一個(gè)函數(shù)來計(jì)算week_of_month def week_of_month(tgtdate): # 由日期型參數(shù)tgtdate計(jì)算該月的天數(shù) days_this_month = calendar.mdays[tgtdate.month] # 通過循環(huán)當(dāng)月的所有天數(shù),找出第二周的第一個(gè)日期 for i in range(1, days_this_month + 1): d = datetime.datetime(tgtdate.year, tgtdate.month, i) if d.day - d.weekday() > 0: startdate = d break # 返回日期所屬月份的第一周 return (tgtdate - startdate).days //7 + 1
df['week_of_month'] = df.date.apply(week_of_month)df.head()
到此為止,我們就完成了數(shù)據(jù)的采集和清洗過程,接下來我們就可以借助該數(shù)據(jù)完成填充熱力(日歷)圖的繪制。 填充熱力圖的繪制
基于matplotlib繪制熱力圖 其實(shí),我需要繪制的是一個(gè)數(shù)據(jù)表,只不過把表中的每一個(gè)單元格用顏色填充起來。而表的結(jié)構(gòu)是:列代表周一到周日,行代表9月份第一周到第五周。很顯然,我們剛剛完成的數(shù)據(jù)并不符合這樣的結(jié)構(gòu),故需要通過pandas模塊中的pivot_table函數(shù)制作一個(gè)透視表,然后才可以繪圖。關(guān)于熱力圖,我們可以使用matplotlib模塊中的pcolor函數(shù),具體我們可以看下方的繪圖語句: # ==================繪圖前的數(shù)據(jù)整理===================== # 構(gòu)建數(shù)據(jù)表(日歷) target = pd.pivot_table(data = df.iloc[:,1:],values = 'high', index = 'week_of_month', columns = 'weekday')target
# 缺失值填充(不填充的話pcolor函數(shù)無法繪制) target.fillna(0,inplace=True) # 刪除表格的索引名稱 target.index.name = None # 對(duì)索引排序(為了讓“第一周”到“第五周”的刻度從y軸的高到底顯示) target.sort_index(ascending=False, inplace=True)
# ======================開始繪圖========================= # 設(shè)置中文和負(fù)號(hào)正常顯示 plt.rcParams['font.sans-serif'] = 'Microsoft YaHei' plt.rcParams['axes.unicode_minus'] = False
plt.pcolor(target, # 指定繪圖數(shù)據(jù) cmap=plt.cm.Blues, # 指定填充色 edgecolors = 'white' # 指點(diǎn)單元格之間的邊框色 )
# 添加x軸和y軸刻度標(biāo)簽(加0.5是為了讓刻度標(biāo)簽居中顯示) plt.xticks(np.arange(7)+0.5,['周一','周二','周三','周四','周五','周六','周日'])plt.yticks(np.arange(5)+0.5,['第五周','第四周','第三周','第二周','第一周'])
# 消除圖框頂部和右部的刻度線 plt.tick_params(top='off', right = 'off') # 添加標(biāo)題 plt.title('上海市2017年9月份每日最高氣溫分布圖') # 顯示圖形 plt.show()
繪圖數(shù)據(jù)的表結(jié)構(gòu) 熱力圖展現(xiàn) OK,一張?zhí)畛浔砀駸崃D就奇跡般的顯示了,而且看上去還蠻舒服的。從圖框看,9月份的第一天是周五,之后的每一天都有對(duì)應(yīng)的顏色顯示。但我在繪圖過程中發(fā)現(xiàn)幾個(gè)問題: 1)繪圖用的數(shù)據(jù),不能包含缺失值,否則填充圖是繪制不出來的,所有需要對(duì)缺失值做填充處理; 2)最終的圖例無法實(shí)現(xiàn),即顏色的深淺,代表了具體的數(shù)值范圍是什么? 3)不方便將具體的溫度值顯示在每個(gè)單元格內(nèi); 為解決上面的三個(gè)問題,我們借助于seaborn模塊中的heatmap函數(shù)重新繪制一下熱力圖,而且這些問題在heatmap函數(shù)看來根本不算問題。 基于seaborn繪制熱力圖# 通過透視圖函數(shù)形成繪圖數(shù)據(jù) target = pd.pivot_table(data = df.iloc[:,1:],values = 'high', index = 'week_of_month', columns = 'weekday')
# 繪圖 ax = sns.heatmap(target, # 指定繪圖數(shù)據(jù) cmap=plt.cm.Blues, # 指定填充色 linewidths=.1, # 設(shè)置每個(gè)單元方塊的間隔 annot=True # 顯示數(shù)值 )
# 添加x軸刻度標(biāo)簽(加0.5是為了讓刻度標(biāo)簽居中顯示) plt.xticks(np.arange(7)+0.5,['周一','周二','周三','周四','周五','周六','周日']) # 可以將刻度標(biāo)簽置于頂部顯示 # ax.xaxis.tick_top()
# 添加y軸刻度標(biāo)簽 plt.yticks(np.arange(5)+0.5,['第一周','第二周','第三周','第四周','第五周']) # 旋轉(zhuǎn)y刻度0度,即水平顯示 plt.yticks(rotation = 0)
# 設(shè)置標(biāo)題和坐標(biāo)軸標(biāo)簽 ax.set_title('上海市2017年9月份每日最高氣溫分布圖')ax.set_xlabel('')ax.set_ylabel('')
# 顯示圖形 plt.show()
完美熱力圖的繪制太簡單了!不需要做任何的特殊處理,只需要將繪圖數(shù)據(jù)扔給heatmap函數(shù)即可。想想是不是有點(diǎn)小激動(dòng)啊~激動(dòng)過后,還得跟著步驟操作一表哦~ 結(jié)語
|