初探Matplotlib 例子來自此書: 《Python編程從入門到實戰》【美】Eric Matthes 使用pyplot繪圖,一般的導入方法 以下代碼均在Jupyter Notebook中運行 折線圖 先看一個簡單的例子 圖如下,可以看到x軸太密了,甚至都有小數。 如果想x軸只出現我們的樣本值,可 ...
初探Matplotlib
例子來自此書: 《Python編程從入門到實戰》【美】Eric Matthes
使用pyplot繪圖,一般的導入方法import matplotlib.pyplot as plt
以下代碼均在Jupyter Notebook中運行
折線圖
先看一個簡單的例子
import matplotlib.pyplot as plt
in_values = [1, 2 ,3, 4, 5]
squares = [1, 4, 9 ,16, 25]
# 第一個參數是X軸輸入,第二個參數是對應的Y軸輸出;linewidth繪製線條的粗細
plt.plot(in_values, squares, linewidth=4)
# 標題、X軸、Y軸
plt.title('Squares', fontsize=20)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Square of the value', fontsize=12)
# plt.tick_params(axis='both', labelsize=15)
plt.show()
圖如下,可以看到x軸太密了,甚至都有小數。
如果想x軸只出現我們的樣本值,可以使用tick_params
函數修改刻度標記的大小。把上面代碼中的倒數第二行取消註釋,得到下麵的圖像。
plt.tick_params(axis='both', labelsize=15)
,其中axis=both
表示同時影響x、y軸的刻度,labelsize
指定了刻度的字型大小,字型大小變大,同一長度下顯示的坐標點數越少,反之亦反。由於將labelsize
設置得比預設大了,故x、y軸顯示的坐標點數變少。更符合這個例子。
散點圖
還是上面的平方例子。這次使用散點圖繪製。
in_values = [1, 2 ,3, 4, 5]
squares = [1, 4, 9 ,16, 25]
# s參數為點的大小
plt.scatter(in_values, squares, s=80)
plt.title('Squares', fontsize=20)
plt.xlabel('Value', fontsize=12)
plt.ylabel('Square of the value', fontsize=12)
plt.tick_params(axis='both', labelsize=15)
plt.show()
可以看到,只是將plt.plot
換成了plt.scatter
,其餘的代碼基本沒變。
若輸入和輸出的點比較多,可使用列表推導式。同時可以指定點的顏色及點的輪廓顏色。預設點的顏色為藍色,輪廓為黑色。
x_values = list(range(1, 100))
y_values = [x**2 for x in x_values]
# c參數指定點的顏色,輪廓的顏色不進行設置(none)
plt.scatter(x_values, y_values, c='red', edgecolors='none' ,s=5)
# x、y軸的坐標範圍,註意提供一個列表,前兩個是x軸的範圍,後兩個是y軸的範圍
plt.axis([0, 110, 0, 11000])
plt.show()
顏色的自定義還可以使用RGB的模式,傳遞一個元組給參數c。元組裡麵包含三個[0, 1]之間的數,分別代表(R, G, B),數字越靠近0顏色越淡,越靠近1顏色越深。比如c=(0, 0 , 0.6)
表示的是一種淺藍色。
依然是平方的圖,人懶就不寫標題了。
顏色映射
顏色映射通常是一系列顏色的漸變。在可視化中,顏色映射可反應數據的規律,比如顏色淺的值比較小,顏色深的值比較大。
看一個很簡單的例子,以y軸坐標值的大小映射。
x_values = list(range(1, 100))
y_values = [x**2 for x in x_values]
# 顏色映射,按照y軸的值從淺到深,顏色採用藍色
plt.scatter(x_values, y_values, c=x_values, cmap=plt.cm.Blues, edgecolors='none' ,s=5)
plt.axis([0, 110, 0, 11000])
# 取代show方法,保存圖片到文件所在目錄,bbox_inches='tight'可裁去多餘的白邊
plt.savefig('squares_plot.png', bbox_inches='tight')
可以看到,y值小的點,顏色很淺,幾乎看不到了;隨著y值則增大,顏色越來越深。
隨機漫步模擬
先寫一個隨機漫步的類,目的是隨機選擇前進的方向
from random import choice
def get_step():
"""
獲得移動的步長
"""
# 分別代表正半軸和負半軸
direction = choice([1, -1])
# 隨機選擇一個距離
distance = choice([0, 1, 2, 3, 4])
step = direction * distance
return step
class RandomWalk:
"""
一個生成隨機漫步數據的類
"""
# 預設漫步5000步
def __init__(self, num_points=5000):
self.num_points = num_points
self.x_values = [0]
self.y_values = [0]
def fill_walk(self):
"""
計算隨機漫步包含的所有點
"""
while len(self.x_values) < self.num_points:
x_step = get_step()
y_step = get_step()
# 沒有位移,跳過不取
if x_step == 0 and y_step == 0:
continue
# 計算下一個點的x和y, 第一次為都0,以前的位置 + 剛纔的位移 = 現在的位置
next_x = self.x_values[-1] + x_step
next_y = self.y_values[-1] + y_step
self.x_values.append(next_x)
self.y_values.append(next_y)
開始繪製
import matplotlib.pyplot as plt
rw = RandomWalk()
rw.fill_walk()
# figure的調用在plot或者scatter之前
# plt.figure(dpi=300, figsize=(10, 6))
# 這個列表包含了各點的漫步順序,第一個元素將是漫步的起點,最後一個元素是漫步的終點
point_numbers = list(range(rw.num_points))
# 使用顏色映射繪製顏色深淺不同的點,淺色的是先漫步的,深色是後漫步的,因此可以反應漫步軌跡
plt.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues, s=1)
# 突出起點
plt.scatter(0, 0, c='green', edgecolors='none', s=50)
# 突出終點
plt.scatter(rw.x_values[-1], rw.y_values[-1], c='red', s=50)
# 隱藏坐標軸
plt.axes().get_xaxis().set_visible(False)
plt.axes().get_yaxis().set_visible(False)
# 指定解析度和圖像大小,單位是英寸
plt.show()
生成的圖片,密密麻麻的點。遠遠看去還挺好看。綠色的是漫步起點,紅色的是漫步的終點。
但是圖片有點不清晰,把rw.fill_walk()
的下麵一行註釋取消。通常在繪圖前調用。
plt.figure(dpi=300, figsize=(10, 6))
,dpi=300
即是300像素/英寸,這個適當調高可獲得清晰的圖片。figsize=(10, 6)
傳入的參數是元組,表示繪圖視窗的尺寸,也就是圖片的尺寸了,單位英寸。
高清大圖,爽不爽?
處理CSV數據
我們也許需要分析別人提供的數據。一般是json和csv兩種格式的文件。這裡有個天氣的數據sitka_weather_2014.csv
,是2014年美國錫特卡的天氣數據。這裡用matplotlib來處理csv文件,json文件的處理放到pygal中。
csv文件的第一行通常是是表頭,真正的數據從第二行開始。我們先看下表頭包含哪些數據。
import csv
filename = 'F:/Jupyter Notebook/matplotlib_pygal_csv_json/sitka_weather_2014.csv'
with open(filename) as f:
reader = csv.reader(f)
# 只調用了一次next,得到第一行表頭
header_row = next(reader)
for index, column_header in enumerate(header_row):
print(index, column_header)
列印如下
0 AKST
1 Max TemperatureF
2 Mean TemperatureF
3 Min TemperatureF
4 Max Dew PointF
5 MeanDew PointF
6 Min DewpointF
7 Max Humidity
8 Mean Humidity
9 Min Humidity
...
我們對最高溫度和最低溫度感興趣,只需要獲得第1列和第3列的數據就行。另外日期數據在第1列。
接下來不難了。從第二行開始,將最高氣溫放入highs列表,最低氣溫放入lows列表,日期放入dates列表我們想要在x軸顯示日期,引入datetime模塊。
import csv
import matplotlib.pyplot as plt
from datetime import datetime
filename = 'F:/Jupyter Notebook/matplotlib_pygal_csv_json/sitka_weather_2014.csv'
with open(filename) as f:
reader = csv.reader(f)
# 只調用了一次next,得到第一行表頭
header_row = next(reader)
# 第一列是最高氣溫,由於上面next讀取過一行了,這裡實際從第二行開始,也是數據開始的那行
# reader只能讀取一次,所以如下寫法dates為空
# highs = [int(row[1]) for row in reader]
# dates= [row[0] for row in reader]
dates, highs, lows = [], [], []
for row in reader:
# 捕獲異常,防止出現數據為空的情況
try:
date = datetime.strptime(row[0], '%Y-%m-%d')
# 第1列最高氣溫,讀取到是字元串,轉為int
high = int(row[1])
# 第3列最低氣溫
low = int(row[3])
except ValueError:
print(date, 'missing data')
else:
dates.append(date)
highs.append(high)
lows.append(low)
# figure在plot之前調用
fig = plt.figure(dpi=300, figsize=(10, 6))
# 最高氣溫的折線圖
plt.plot(dates, highs, c='red')
# 最低氣溫的折線圖
plt.plot(dates, lows, c='blue')
# 在兩個y值之間填充顏色,facecolor為填充的顏色,alpha參數可指定顏色透明度,0.1表示顏色很淺接近透明
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
plt.title('Daily high and low temperatures - 2014', fontsize=20)
plt.xlabel('', fontsize=16)
plt.ylabel('Temperature(F)', fontsize=16)
# x軸的日期調整為斜著顯示
fig.autofmt_xdate()
plt.tick_params(axis='both',labelsize=15)
plt.show()
看以看出,7月到9月都很熱,但是5月出現過非常高的氣溫!
上面的代碼有一行date = datetime.strptime(row[0], '%Y-%m-%d')
。註意%Y-%m-%d
要和row[0]
字元串的格式一致。舉個例子
# 下麵這句報錯time data '2017/6/23' does not match format '%Y-%m-%d'
print(datetime.strptime('2017/6/22', '%Y-%m-%d'))
print(datetime.strptime('2017-6-22', '%Y-%m-%d'))
%Y
指的是四位的年份, %y
是兩位年份,%m
是數字表示的月份,%d
數字表示的月份中的一天。
by @sunhaiyu
2017.6.22