Matplotlib 入門教程
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
第一章 Matplotlib 簡介
歡迎閱讀 Python 3+ Matplotlib 系列教程良瞧。 在本系列中寺酪,我們將涉及 Matplotlib 數(shù)據(jù)可視化模塊的多個(gè)方面军洼。 Matplotlib 能夠創(chuàng)建多數(shù)類型的圖表争拐,如條形圖碑诉,散點(diǎn)圖酷愧,條形圖找田,餅圖誉简,堆疊圖,3D 圖和地圖圖表。
首先废岂,為了實(shí)際使用 Matplotlib祖搓,我們需要安裝它。
如果你安裝了更高版本的 Python湖苞,你應(yīng)該能夠打開cmd.exe
或終端拯欧,然后執(zhí)行:
pip install matplotlib
注意:如果上面的較短命令不工作,你可能需要執(zhí)行C:/Python34/Scripts/pip install matplotlib
财骨。
如果在導(dǎo)入matplotlib
時(shí)镐作,你會(huì)收到類似『無命名模塊』和模塊名稱的錯(cuò)誤,這意味著你還需要安裝該模塊隆箩。 一個(gè)常見的問題是缺少名為six
的模塊该贾。 這意味著你需要使用pip
安裝six
。
或者捌臊,你可以前往 Matplotlib.org 并通過訪問下載頁面下載適當(dāng)?shù)陌姹具M(jìn)行安裝杨蛋。 請記住,因?yàn)槟愕牟僮飨到y(tǒng)為 64 位理澎,你不一定需要 64 位版本的 Python逞力。 如果你不打算嘗試 64 位,你可以使用 32 位糠爬。 打開 IDLE 并閱讀頂部寇荧。 如果它說你是 64 位,你就是 64 位执隧,如果它說是 32 位揩抡,那么你就是 32 位。 一旦你安裝了 Python镀琉,你就做好了準(zhǔn)備峦嗤,你可以編寫任何你想要的邏輯。 我喜歡使用 IDLE 來編程滚粟,但你可以隨意使用任何你喜歡的東西寻仗。
import matplotlib.pyplot as plt
這一行導(dǎo)入集成的pyplot
,我們將在整個(gè)系列中使用它凡壤。 我們將pyplot
導(dǎo)入為plt
署尤,這是使用pylot
的 python 程序的傳統(tǒng)慣例。
plt.plot([1,2,3],[5,7,4])
接下來亚侠,我們調(diào)用plot
的.plot
方法繪制一些坐標(biāo)曹体。 這個(gè).plot
需要許多參數(shù),但前兩個(gè)是'x'
和'y'
坐標(biāo)硝烂,我們放入列表箕别。 這意味著,根據(jù)這些列表我們擁有 3 個(gè)坐標(biāo):1,5
2,7
和3,4
。
plt.plot
在后臺(tái)『繪制』這個(gè)繪圖串稀,但繪制了我們想要的一切之后除抛,當(dāng)我們準(zhǔn)備好的時(shí)候,我們需要把它帶到屏幕上母截。
plt.show()
這樣到忽,應(yīng)該彈出一個(gè)圖形。 如果沒有清寇,有時(shí)它可以彈出喘漏,或者你可能得到一個(gè)錯(cuò)誤。 你的圖表應(yīng)如下所示:
這個(gè)窗口是一個(gè) matplotlib 窗口华烟,它允許我們查看我們的圖形翩迈,以及與它進(jìn)行交互和訪問。 你可以將鼠標(biāo)懸停在圖表上盔夜,并查看通常在右下角的坐標(biāo)负饲。 你也可以使用按鈕。 它們可能在不同的位置比吭,但在上圖中绽族,這些按鈕在左下角。
Home
(主頁)
一旦你開始瀏覽你的圖表衩藤,主頁按鈕會(huì)幫助你。 如果你想要返回原始視圖涛漂,可以單擊它赏表。 在瀏覽圖表之前單擊此按鈕將不會(huì)生效。
Forward/Back
(前進(jìn)/后退)
這些按鈕可以像瀏覽器中的前進(jìn)和后退按鈕一樣使用匈仗。 你可以單擊這些來移回到你之前的位置瓢剿,或再次前進(jìn)。
Pan
(平移)
你可以點(diǎn)擊平移按鈕悠轩,之后點(diǎn)擊并拖拽你的圖表间狂。
Zoom
(縮放)
縮放按鈕可讓你單擊它威鹿,然后單擊并拖動(dòng)出要放大的方形區(qū)域字支。 放大需要左鍵單擊并拖動(dòng)。 你也可以右鍵單擊并拖動(dòng)來縮小古胆。
Configure Subplots
(配置子圖)
此按鈕允許你對圖形和繪圖配置各種間距選項(xiàng)何鸡。 點(diǎn)擊它會(huì)彈出:
每個(gè)藍(lán)色條形都是一個(gè)滑塊纺弊,它允許你調(diào)整內(nèi)邊距。 其中有些現(xiàn)在沒有任何效果骡男,因?yàn)闆]有任何其他子圖淆游。 前四個(gè)值調(diào)整圖形到窗口邊緣的邊距。 之后wspace
和hspace
對應(yīng)于當(dāng)你繪制多個(gè)子圖時(shí),它們的水平或豎直間距犹菱。
Save
(保存)
此按鈕允許你以各種形式保存圖形拾稳。
所以這是 matplotlib 的快速介紹,我們之后會(huì)涉及更多腊脱。
第二章 圖例熊赖、標(biāo)題和標(biāo)簽
在本教程中,我們將討論 Matplotlib 中的圖例虑椎,標(biāo)題和標(biāo)簽震鹉。 很多時(shí)候,圖形可以不言自明捆姜,但是圖形帶有標(biāo)題传趾,軸域上的標(biāo)簽和圖例,來解釋每一行是什么非常必要泥技。
注:軸域(
Axes
)即兩條坐標(biāo)軸圍城的區(qū)域浆兰。
從這里開始:
import matplotlib.pyplot as plt
x = [1,2,3]
y = [5,7,4]
x2 = [1,2,3]
y2 = [10,14,12]
這樣我們可以畫出兩個(gè)線條,接下來:
plt.plot(x, y, label='First Line')
plt.plot(x2, y2, label='Second Line')
在這里珊豹,我們繪制了我們已經(jīng)看到的東西簸呈,但這次我們添加另一個(gè)參數(shù)label
。 這允許我們?yōu)榫€條指定名稱店茶,我們以后可以在圖例中顯示它蜕便。 我們的其余代碼為:
plt.xlabel('Plot Number')
plt.ylabel('Important var')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
使用plt.xlabel
和plt.ylabel
,我們可以為這些相應(yīng)的軸創(chuàng)建標(biāo)簽贩幻。 接下來轿腺,我們可以使用plt.title
創(chuàng)建圖的標(biāo)題,然后我們可以使用plt.legend()
生成默認(rèn)圖例丛楚。 結(jié)果圖如下:
第三章 條形圖和直方圖
這個(gè)教程中我們會(huì)涉及條形圖和直方圖族壳。我們先來看條形圖:
import matplotlib.pyplot as plt
plt.bar([1,3,5,7,9],[5,2,7,8,2], label="Example one")
plt.bar([2,4,6,8,10],[8,6,2,5,6], label="Example two", color='g')
plt.legend()
plt.xlabel('bar number')
plt.ylabel('bar height')
plt.title('Epic Graph\nAnother Line! Whoa')
plt.show()
plt.bar
為我們創(chuàng)建條形圖。 如果你沒有明確選擇一種顏色趣些,那么雖然做了多個(gè)圖仿荆,所有的條看起來會(huì)一樣。 這讓我們有機(jī)會(huì)使用一個(gè)新的 Matplotlib 自定義選項(xiàng)坏平。 你可以在任何類型的繪圖中使用顏色拢操,例如g
為綠色,b
為藍(lán)色功茴,r
為紅色庐冯,等等。 你還可以使用十六進(jìn)制顏色代碼坎穿,如#191970
展父。
接下來返劲,我們會(huì)講解直方圖。 直方圖非常像條形圖栖茉,傾向于通過將區(qū)段組合在一起來顯示分布篮绿。 這個(gè)例子可能是年齡的分組,或測試的分?jǐn)?shù)吕漂。 我們并不是顯示每一組的年齡亲配,而是按照 20 ~ 25,25 ~ 30... 等等來顯示年齡惶凝。 這里有一個(gè)例子:
import matplotlib.pyplot as plt
population_ages = [22,55,62,45,21,22,34,42,42,4,99,102,110,120,121,122,130,111,115,112,80,75,65,54,44,43,42,48]
bins = [0,10,20,30,40,50,60,70,80,90,100,110,120,130]
plt.hist(population_ages, bins, histtype='bar', rwidth=0.8)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
產(chǎn)生的圖表為:
對于plt.hist
吼虎,你首先需要放入所有的值,然后指定放入哪個(gè)桶或容器苍鲜。 在我們的例子中思灰,我們繪制了一堆年齡,并希望以 10 年的增量來顯示它們混滔。 我們將條形的寬度設(shè)為 0.8洒疚,但是如果你想讓條形變寬,或者變窄坯屿,你可以選擇其他的寬度油湖。
第四章 散點(diǎn)圖
接下來,我們將介紹散點(diǎn)圖领跛。散點(diǎn)圖通常用于比較兩個(gè)變量來尋找相關(guān)性或分組乏德,如果你在 3 維繪制則是 3 個(gè)。
散點(diǎn)圖的一些示例代碼:
import matplotlib.pyplot as plt
x = [1,2,3,4,5,6,7,8]
y = [5,2,4,2,1,4,5,2]
plt.scatter(x,y, label='skitscat', color='k', s=25, marker="o")
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
結(jié)果為:
plt.scatter
不僅允許我們繪制x
和y
隔节,而且還可以讓我們決定所使用的標(biāo)記顏色鹅经,大小和類型。 有一堆標(biāo)記選項(xiàng)怎诫,請參閱 Matplotlib 標(biāo)記文檔中的所有選項(xiàng)。
第五章 堆疊圖
在這篇 Matplotlib 數(shù)據(jù)可視化教程中贷痪,我們要介紹如何創(chuàng)建堆疊圖幻妓。 堆疊圖用于顯示『部分對整體』隨時(shí)間的關(guān)系。 堆疊圖基本上類似于餅圖劫拢,只是隨時(shí)間而變化肉津。
讓我們考慮一個(gè)情況,我們一天有 24 小時(shí)舱沧,我們想看看我們?nèi)绾位ㄙM(fèi)時(shí)間妹沙。 我們將我們的活動(dòng)分為:睡覺,吃飯熟吏,工作和玩耍距糖。
我們假設(shè)我們要在 5 天的時(shí)間內(nèi)跟蹤它玄窝,因此我們的初始數(shù)據(jù)將如下所示:
import matplotlib.pyplot as plt
days = [1,2,3,4,5]
sleeping = [7,8,6,11,7]
eating = [2,3,4,3,2]
working = [7,8,7,2,2]
playing = [8,5,7,8,13]
因此,我們的x
軸將包括day
變量悍引,即 1, 2, 3, 4 和 5恩脂。然后,日期的各個(gè)成分保存在它們各自的活動(dòng)中趣斤。 像這樣繪制它們:
plt.stackplot(days, sleeping,eating,working,playing, colors=['m','c','r','k'])
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.show()
在這里俩块,我們可以至少在顏色上看到,我們?nèi)绾位ㄙM(fèi)我們的時(shí)間浓领。 問題是玉凯,如果不回頭看代碼,我們不知道什么顏色是什么联贩。 下一個(gè)問題是漫仆,對于多邊形來說,我們實(shí)際上不能為數(shù)據(jù)添加『標(biāo)簽』撑蒜。 因此歹啼,在任何不止是線條,帶有像這樣的填充或堆疊圖的地方座菠,我們不能以固有方式標(biāo)記出特定的部分狸眼。 這不應(yīng)該阻止程序員。 我們可以解決這個(gè)問題:
import matplotlib.pyplot as plt
days = [1,2,3,4,5]
sleeping = [7,8,6,11,7]
eating = [2,3,4,3,2]
working = [7,8,7,2,2]
playing = [8,5,7,8,13]
plt.plot([],[],color='m', label='Sleeping', linewidth=5)
plt.plot([],[],color='c', label='Eating', linewidth=5)
plt.plot([],[],color='r', label='Working', linewidth=5)
plt.plot([],[],color='k', label='Playing', linewidth=5)
plt.stackplot(days, sleeping,eating,working,playing, colors=['m','c','r','k'])
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
我們在這里做的是畫一些空行浴滴,給予它們符合我們的堆疊圖的相同顏色拓萌,和正確標(biāo)簽。 我們還使它們線寬為 5升略,使線條在圖例中顯得較寬微王。 現(xiàn)在,我們可以很容易地看到品嚣,我們?nèi)绾位ㄙM(fèi)我們的時(shí)間炕倘。
第六章 餅圖
餅圖很像堆疊圖,只是它們位于某個(gè)時(shí)間點(diǎn)翰撑。 通常罩旋,餅圖用于顯示部分對于整體的情況,通常以%為單位眶诈。 幸運(yùn)的是涨醋,Matplotlib 會(huì)處理切片大小以及一切事情,我們只需要提供數(shù)值逝撬。
import matplotlib.pyplot as plt
slices = [7,2,2,13]
activities = ['sleeping','eating','working','playing']
cols = ['c','m','r','b']
plt.pie(slices,
labels=activities,
colors=cols,
startangle=90,
shadow= True,
explode=(0,0.1,0,0),
autopct='%1.1f%%')
plt.title('Interesting Graph\nCheck it out')
plt.show()
在plt.pie
中浴骂,我們需要指定『切片』,這是每個(gè)部分的相對大小宪潮。 然后溯警,我們指定相應(yīng)切片的顏色列表趣苏。 接下來,我們可以選擇指定圖形的『起始角度』愧膀。 這使你可以在任何地方開始繪圖拦键。 在我們的例子中,我們?yōu)轱瀳D選擇了 90 度角檩淋,這意味著第一個(gè)部分是一個(gè)豎直線條芬为。 接下來,我們可以選擇給繪圖添加一個(gè)字符大小的陰影蟀悦,然后我們甚至可以使用explode
拉出一個(gè)切片媚朦。
我們總共有四個(gè)切片,所以對于explode
日戈,如果我們不想拉出任何切片询张,我們傳入0,0,0,0
。 如果我們想要拉出第一個(gè)切片浙炼,我們傳入0.1,0,0,0
份氧。
最后,我們使用autopct
弯屈,選擇將百分比放置到圖表上面蜗帜。
第七章 從文件加載數(shù)據(jù)
很多時(shí)候,我們想要繪制文件中的數(shù)據(jù)资厉。 有許多類型的文件厅缺,以及許多方法,你可以使用它們從文件中提取數(shù)據(jù)來圖形化宴偿。 在這里湘捎,我們將展示幾種方法。 首先窄刘,我們將使用內(nèi)置的csv
模塊加載CSV文件窥妇,然后我們將展示如何使用 NumPy(第三方模塊)加載文件。
import matplotlib.pyplot as plt
import csv
x = []
y = []
with open('example.txt','r') as csvfile:
plots = csv.reader(csvfile, delimiter=',')
for row in plots:
x.append(int(row[0]))
y.append(int(row[1]))
plt.plot(x,y, label='Loaded from file!')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
這里娩践,我們打開樣例文件秩伞,包含以下數(shù)據(jù):
1,5
2,3
3,4
4,7
5,4
6,3
7,5
8,7
9,4
10,4
接下來,我們使用csv
模塊讀取數(shù)據(jù)欺矫。 csv
讀取器自動(dòng)按行分割文件,然后使用我們選擇的分隔符分割文件中的數(shù)據(jù)展氓。 在我們的例子中穆趴,這是一個(gè)逗號(hào)。 注意:csv
模塊和csv reader
不需要文件在字面上是一個(gè).csv文件遇汞。 它可以是任何具有分隔數(shù)據(jù)的簡單的文本文件未妹。
一旦我們這樣做了簿废,我們將索引為 0 的元素存儲(chǔ)到x
列表,將索引為 1 的元素存儲(chǔ)到y
列表中络它。 之后族檬,我們都設(shè)置好了,準(zhǔn)備繪圖化戳,然后顯示數(shù)據(jù)单料。
雖然使用 CSV 模塊是完全正常的,但使用 NumPy 模塊來加載我們的文件和數(shù)據(jù)点楼,可能對我們更有意義扫尖。 如果你沒有 NumPy,你需要按下面的步驟來獲取它掠廓。 為了了解安裝模塊的更多信息换怖,請參閱 pip 教程。 大多數(shù)人應(yīng)該都能打開命令行谦纱,并執(zhí)行pip install numpy
尸饺。
如果不能促脉,請參閱鏈接中的教程。
一旦你安裝了 NumPy铸屉,你可以編寫如下代碼:
import matplotlib.pyplot as plt
import numpy as np
x, y = np.loadtxt('example.txt', delimiter=',', unpack=True)
plt.plot(x,y, label='Loaded from file!')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
結(jié)果應(yīng)該是相同的圖表。 稍后塞关,當(dāng)我們加載數(shù)據(jù)時(shí)抬探,我們可以利用 NumPy 為我們做一些更多的工作,但這是教程未來的內(nèi)容帆赢。 就像csv
模塊不需要一個(gè)特地的.csv
一樣小压,loadtxt
函數(shù)不要求文件是一個(gè).txt
文件,它可以是一個(gè).csv
椰于,它甚至可以是一個(gè) python 列表對象怠益。
第八章 從網(wǎng)絡(luò)加載數(shù)據(jù)
除了從文件加載數(shù)據(jù),另一個(gè)流行的數(shù)據(jù)源是互聯(lián)網(wǎng)瘾婿。 我們可以用各種各樣的方式從互聯(lián)網(wǎng)加載數(shù)據(jù)蜻牢,但對我們來說,我們只是簡單地讀取網(wǎng)站的源代碼偏陪,然后通過簡單的拆分來分離數(shù)據(jù)抢呆。
import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates
def graph_data(stock):
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line:
stock_data.append(line)
這里有很多步驟。首先笛谦,我們看到import
抱虐。 pyplot
像往常一樣導(dǎo)入,然后導(dǎo)入了numpy
饥脑,然后是用于訪問互聯(lián)網(wǎng)的urllib
恳邀,然后導(dǎo)入了matplotlib.dates
作為mdates
懦冰,它對于將日期戳轉(zhuǎn)換為 matplotlib 可以理解的日期很有用。
接下來谣沸,我們開始構(gòu)建我們的graph_data
函數(shù)刷钢。在這里,我們首先定義包含股票數(shù)據(jù)的網(wǎng)址乳附。之后内地,我們寫一些urllib
代碼來訪問該 URL,然后使用.read
讀取源代碼许溅,之后我們繼續(xù)解碼該數(shù)據(jù)瓤鼻。如果你使用 Python 2,則不必使用decode
贤重。
然后茬祷,我們定義一個(gè)空列表,這是我們將要放置股票數(shù)據(jù)的地方并蝗,我們也開始使用split_source
變量拆分?jǐn)?shù)據(jù)祭犯,以換行符拆分。
現(xiàn)在滚停,如果你去看源代碼沃粗,用stock
替換 URL 中的+stock+
,像 AAPL 那樣键畴,你可以看到大多數(shù)頁面數(shù)據(jù)確實(shí)是股票定價(jià)信息最盅,但有一些頭信息我們需要過濾掉。為此起惕,我們使用一些基本的過濾涡贱,檢查它們來確保每行有 6 個(gè)數(shù)據(jù)點(diǎn),然后確保術(shù)語values
不在行中惹想。
現(xiàn)在问词,我們已經(jīng)解析了數(shù)據(jù),并做好了準(zhǔn)備嘀粱。我們將使用 NumPy:
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
# %Y = full year. 2015
# %y = partial year 15
# %m = number month
# %d = number day
# %H = hours
# %M = minutes
# %S = seconds
# 12-06-2014
# %m-%d-%Y
converters={0: bytespdate2num('%Y%m%d')})
我們在這里所做的是激挪,使用numpy
的loadtxt
函數(shù),并將這六個(gè)元素解構(gòu)到六個(gè)變量锋叨。 這里的第一個(gè)參數(shù)是stock_data
垄分,這是我們加載的數(shù)據(jù)。 然后娃磺,我們指定delimiter
(這里是逗號(hào))锋喜,然后我們指定我們確實(shí)想要在這里解包變量,不是一個(gè)變量,而是我們定義的這組變量嘿般。 最后,我們使用可選的converters
參數(shù)來指定我們要轉(zhuǎn)換的元素(0
)涯冠,以及我們打算要怎么做炉奴。 我們傳遞一個(gè)名為bytespdate2num
的函數(shù),它還不存在蛇更,但我們下面會(huì)編寫它瞻赶。
第九章 時(shí)間戳的轉(zhuǎn)換
本教程的重點(diǎn)是將來自 Yahoo finance API 的日期轉(zhuǎn)換為 Matplotlib 可理解的日期。 為了實(shí)現(xiàn)它派任,我們要寫一個(gè)新的函數(shù)砸逊,bytespdate2num
。
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
此函數(shù)接受數(shù)據(jù)掌逛,基于編碼來解碼數(shù)據(jù)师逸,然后返回它。
將此應(yīng)用于我們的程序的其余部分:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
# %Y = full year. 2015
# %y = partial year 15
# %m = number month
# %d = number day
# %H = hours
# %M = minutes
# %S = seconds
# 12-06-2014
# %m-%d-%Y
converters={0: bytespdate2num('%Y%m%d')})
plt.plot_date(date, closep,'-', label='Price')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
graph_data('TSLA')
如果你繪制 TSLA豆混,結(jié)果圖應(yīng)該看起來像這樣:
第十章 基本的自定義
在 Matplotlib 教程中篓像,我們將討論一些可能的圖表自定義。 為了開始修改子圖皿伺,我們必須定義它們员辩。 我們很快會(huì)談?wù)撍麄儯袃煞N定義并構(gòu)造子圖的主要方法鸵鸥。 現(xiàn)在奠滑,我們只使用其中一個(gè),但我們會(huì)很快解釋它們妒穴。
現(xiàn)在宋税,修改我們的graph_data
函數(shù):
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
為了修改圖表,我們需要引用它宰翅,所以我們將它存儲(chǔ)到變量fig
弃甥。 然后我們將ax1
定義為圖表上的子圖。 我們在這里使用subplot2grid
汁讼,這是獲取子圖的兩種主要方法之一淆攻。 我們將深入討論這些東西,但現(xiàn)在嘿架,你應(yīng)該看到我們有 2 個(gè)元組瓶珊,它們提供了(1,1)
和(0,0)
。 1,1
表明這是一個(gè) 1×1 網(wǎng)格耸彪。 然后0,0
表明這個(gè)子圖的『起點(diǎn)』將為0,0
伞芹。
接下來,通過我們已經(jīng)編寫的代碼來獲取和解析數(shù)據(jù):
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
下面,我們這樣繪制數(shù)據(jù):
ax1.plot_date(date, closep,'-', label='Price')
現(xiàn)在唱较,由于我們正在繪制日期扎唾,我們可能會(huì)發(fā)現(xiàn),如果我們放大南缓,日期會(huì)在水平方向上移動(dòng)胸遇。但是,我們可以自定義這些刻度標(biāo)簽汉形,像這樣:
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
這將使標(biāo)簽轉(zhuǎn)動(dòng)到對角線方向纸镊。 接下來,我們可以添加一個(gè)網(wǎng)格:
ax1.grid(True)
然后概疆,其它東西我們保留默認(rèn)逗威,但我們也可能需要略微調(diào)整繪圖,因?yàn)槿掌谂艿搅藞D表外面岔冀。 記不記得我們在第一篇教程中討論的configure subplots
按鈕凯旭? 我們不僅可以以這種方式配置圖表,我們還可以在代碼中配置它們楣颠,以下是我們設(shè)置這些參數(shù)的方式:
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
現(xiàn)在尽纽,為了防止我們把你遺留在某個(gè)地方,這里是完整的代碼:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
ax1.plot_date(date, closep,'-', label='Price')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('TSLA')
結(jié)果為:
第十一章 Unix 時(shí)間
在這個(gè) Matplotlib 教程中童漩,我們將介紹如何處理 unix 時(shí)間戳的轉(zhuǎn)換弄贿,然后在圖形中繪制日期戳。 使用 Yahoo Finance API矫膨,你會(huì)注意到差凹,如果你使用較大的時(shí)間間隔,如1y
(一年)侧馅,你會(huì)得到我們一直在使用的日期戳危尿,但如果你使用10d
(10 天),反之你會(huì)得到 unix 時(shí)間的時(shí)間戳馁痴。
Unix 時(shí)間是 1970 年 1 月 1 日以后的秒數(shù)谊娇,它是跨程序的標(biāo)準(zhǔn)化時(shí)間表示方法。 也就是說罗晕,Matplotlib 并不歡迎 unix 時(shí)間戳济欢。 這里是你可以使用 Matplotlib 來處理 unix 時(shí)間的方式:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10d/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True)
dateconv = np.vectorize(dt.datetime.fromtimestamp)
date = dateconv(date)
## date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
## delimiter=',',
## unpack=True,
## converters={0: bytespdate2num('%Y%m%d')})
ax1.plot_date(date, closep,'-', label='Price')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('TSLA')
所以在這里,我們所做的是 unix 時(shí)間的寫入處理小渊,并注釋掉我們以前的代碼法褥,因?yàn)槲覀優(yōu)橹蟮氖褂枚4嫠?這里的主要區(qū)別是:
dateconv = np.vectorize(dt.datetime.fromtimestamp)
date = dateconv(date)
這里,我們將時(shí)間戳轉(zhuǎn)換為日期戳酬屉,然后將其轉(zhuǎn)換為 Matplotlib 想要的時(shí)間半等。
現(xiàn)在揍愁,由于某些原因,我的 unix 時(shí)間帶有另一行包含 6 個(gè)元素的數(shù)據(jù)杀饵,并且它包含了術(shù)語label
莽囤,因此,在我們解析數(shù)據(jù)的for
循環(huán)中凹髓,我們?yōu)槟阍偬砑右粋€(gè)需要注意的檢查:
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
現(xiàn)在你的圖表應(yīng)該類似:
這里的所有扁平線條的原因是市場關(guān)閉烁登。 有了這個(gè)短期數(shù)據(jù),我們可以得到日內(nèi)數(shù)據(jù)蔚舀。 所以交易開放時(shí)有很多點(diǎn),然后市場關(guān)閉時(shí)就沒有了锨络,然后又是一堆赌躺,然后又是沒有。
第十二章 顏色和填充
在本教程中羡儿,我們將介紹一些更多的自定義礼患,比如顏色和線條填充。
我們要做的第一個(gè)改動(dòng)是將plt.title
更改為stock
變量掠归。
plt.title(stock)
現(xiàn)在缅叠,讓我們來介紹一下如何更改標(biāo)簽顏色。 我們可以通過修改我們的軸對象來實(shí)現(xiàn):
ax1.xaxis.label.set_color('c')
ax1.yaxis.label.set_color('r')
如果我們運(yùn)行它虏冻,我們會(huì)看到標(biāo)簽改變了顏色肤粱,就像在單詞中那樣。
接下來厨相,我們可以為要顯示的軸指定具體數(shù)字领曼,而不是像這樣的自動(dòng)選擇:
ax1.set_yticks([0,25,50,75])
接下來,我想介紹填充蛮穿。 填充所做的事情庶骄,是在變量和你選擇的一個(gè)數(shù)值之間填充顏色。 例如践磅,我們可以這樣:
ax1.fill_between(date, 0, closep)
所以到這里单刁,我們的代碼為:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
ax1.fill_between(date, 0, closep)
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
ax1.xaxis.label.set_color('c')
ax1.yaxis.label.set_color('r')
ax1.set_yticks([0,25,50,75])
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
結(jié)果為:
填充的一個(gè)問題是,我們可能最后會(huì)把東西都覆蓋起來府适。 我們可以用透明度來解決它:
ax1.fill_between(date, 0, closep)
現(xiàn)在羔飞,讓我們介紹條件填充。 讓我們假設(shè)圖表的起始位置是我們開始買入 eBay 的地方细溅。 這里褥傍,如果價(jià)格低于這個(gè)價(jià)格,我們可以向上填充到原來的價(jià)格喇聊,然后如果它超過了原始價(jià)格恍风,我們可以向下填充。 我們可以這樣做:
ax1.fill_between(date, closep[0], closep)
會(huì)生成:
如果我們想用紅色和綠色填充來展示收益/損失,那么與原始價(jià)格相比朋贬,綠色填充用于上升(注:國外股市的顏色和國內(nèi)相反)凯楔,紅色填充用于下跌? 沒問題锦募! 我們可以添加一個(gè)where
參數(shù)摆屯,如下所示:
ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
這里,我們填充當(dāng)前價(jià)格和原始價(jià)格之間的區(qū)域,其中當(dāng)前價(jià)格高于原始價(jià)格。 我們給予它綠色的前景色咬荷,因?yàn)檫@是一個(gè)上升奠涌,而且我們使用微小的透明度。
我們?nèi)匀徊荒軐Χ噙呅螖?shù)據(jù)(如填充)應(yīng)用標(biāo)簽,但我們可以像以前一樣實(shí)現(xiàn)空線條,因此我們可以:
ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)
這向我們提供了一些填充,以及用于處理標(biāo)簽的空線條颠黎,我們打算將其顯示在圖例中。這里完整的代碼是:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
ax1.plot_date(date, closep,'-', label='Price')
ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
ax1.xaxis.label.set_color('c')
ax1.yaxis.label.set_color('r')
ax1.set_yticks([0,25,50,75])
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
現(xiàn)在我們的結(jié)果是:
第十三章 邊框和水平線條
歡迎閱讀另一個(gè)定制教程滞项,在這里我們使用 Matplotlib 討論邊框和水平線條狭归。 有時(shí)候你可能想做的事情是改變邊框的顏色,或者甚至完全刪除它們文判。
圖形的邊框基本上是圖形的邊界过椎,其中有刻度線等東西。為了改變邊框的顏色律杠,你可以做一些類似這樣的事情:
ax1.spines['left'].set_color('c')
在這里潭流,我們引用了我們的邊框字典,表示我們要調(diào)整左邊框柜去,然后我們使用set_color
方法將顏色設(shè)置為'c'
灰嫉,它是青色。
如果我們想刪除所有邊框怎么辦嗓奢? 我們可以這樣做:
ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)
這是非常類似的代碼讼撒,刪除了右邊框和上邊框。
很難看到我們修改了左邊框的顏色股耽,所以讓我們通過修改線寬來使它變得很明顯:
ax1.spines['left'].set_linewidth(5)
現(xiàn)在根盒,左邊框變成了非常粗也非常顯眼的青色。 最后物蝙,如果我們想修改刻度參數(shù)怎么辦炎滞? 假如不想要黑色的日期,我們想要一些橙色的日期诬乞? 沒問題册赛!
ax1.tick_params(axis='x', colors='#f06215')
現(xiàn)在我們的日期是橙色了钠导! 接下來,讓我們來看看我們?nèi)绾卫L制一條水平線森瘪。 你當(dāng)然可以將你創(chuàng)建的一組新數(shù)據(jù)繪制成一條水平線牡属,但你不需要這樣做。 你可以:
ax1.axhline(closep[0], color='k', linewidth=5)
所以在這里扼睬,我們的整個(gè)代碼是:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
ax1.plot_date(date, closep,'-', label='Price')
ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)
ax1.axhline(closep[0], color='k', linewidth=5)
ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.grid(True)
#ax1.xaxis.label.set_color('c')
#ax1.yaxis.label.set_color('r')
ax1.set_yticks([0,25,50,75])
ax1.spines['left'].set_color('c')
ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax1.spines['left'].set_linewidth(5)
ax1.tick_params(axis='x', colors='#f06215')
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('ebay')
結(jié)果為:
第十四章 OHLC K 線圖
在 Matplotlib 教程中逮栅,我們將介紹如何在 Matplotlib 中創(chuàng)建開,高窗宇,低措伐,關(guān)(OHLC)的 K 線圖。 這些圖表用于以精簡形式顯示時(shí)間序列股價(jià)信息军俊。 為了實(shí)現(xiàn)它废士,我們首先需要導(dǎo)入一些模塊:
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
我們引入了ticker
,允許我們修改圖表底部的ticker
信息蝇完。 然后我們從matplotlib.finance
模塊中引入candlestick_ohlc
功能。
現(xiàn)在矗蕊,我們需要組織我們的數(shù)據(jù)來和 matplotlib 協(xié)作短蜕。 如果你剛剛加入我們,我們得到的數(shù)據(jù)如下:
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
現(xiàn)在傻咖,我們需要構(gòu)建一個(gè) Python 列表朋魔,其中每個(gè)元素都是數(shù)據(jù)。 我們可以修改我們的loadtxt
函數(shù)卿操,使其不解構(gòu)警检,但隨后我們還是希望引用特定的數(shù)據(jù)點(diǎn)。 我們可以解決這個(gè)問題害淤,但是我們最后可能只擁有兩個(gè)單獨(dú)的數(shù)據(jù)集扇雕。 為此,我們執(zhí)行以下操作:
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
有了這個(gè)窥摄,我們現(xiàn)在將 OHLC 數(shù)據(jù)列表存儲(chǔ)到我們的變量ohlc
镶奉。 現(xiàn)在我們可以這樣繪制:
candlestick_ohlc(ax1, ohlc)
圖表應(yīng)該是這樣:
不幸的是,x
軸上的datetime
數(shù)據(jù)不是日期戳的形式崭放。 我們可以處理它:
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
此外哨苛,紅/黑著色依我看不是最好的選擇。 我們應(yīng)該使用綠色表示上升和紅色表示下降币砂。 為此建峭,我們可以:
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
最后,我們可以將x
標(biāo)簽設(shè)置為我們想要的數(shù)量决摧,像這樣:
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
現(xiàn)在亿蒸,完整代碼現(xiàn)在是這樣:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
import numpy as np
import urllib
import datetime as dt
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.grid(True)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
結(jié)果為:
還要注意凑兰,我們從前面的教程中刪除了大部分ax1
的修改。
第十五章 樣式
在這個(gè) Matplotlib 教程中祝懂,我們將討論樣式票摇。 我們用于 Matplotlib 的樣式非常相似于用于 HTML 頁面的 CSS(層疊樣式表)。 正如你在這里可以看到的砚蓬,我們對圖形所做的所有修改都會(huì)疊加矢门,而且我們目前只有一個(gè)軸域。 我們可以使用for
循環(huán)灰蛙,至少使代碼量降低祟剔,但我們也可以在 Matplotlib 中利用這些樣式。
樣式頁的想法是將自定義樣式寫入文件摩梧,然后物延,為了使用這些更改并將其應(yīng)用于圖形,所有你需要做的就是導(dǎo)入樣式仅父,然后使用該特定樣式叛薯。 這樣,讓我們假設(shè)你發(fā)現(xiàn)自己總是改變圖形的各種元素笙纤。 你不必為每個(gè)圖表編寫 25 ~ 200 行自定義代碼耗溜,只需將其寫入一個(gè)樣式,然后加載該樣式省容,并以兩行應(yīng)用所有這些更改即可抖拴! 讓我們開始吧。
from matplotlib import style
接下來腥椒,我們指定要使用的樣式阿宅。 Matplotlib 已經(jīng)有了幾種樣式。
我們可以這樣來使用樣式:
style.use('ggplot')
除了標(biāo)題笼蛛,標(biāo)簽的顏色是灰色的洒放,軸域的背景是淺灰色,我們可以立即分辨字體是不同的伐弹。 我們還注意到拉馋,網(wǎng)格實(shí)際上是一個(gè)白色的實(shí)線。 我們的 K 線圖保持不變惨好,主要是因?yàn)槲覀冊谑潞蠖ㄖ扑?在樣式中加載時(shí)煌茴,更改會(huì)生效,但如果在加載樣式后編寫新的自定義代碼日川,你的更改也會(huì)生效蔓腐。
因?yàn)槲覀冊噲D展示樣式模塊,但是讓我們繼續(xù)龄句,簡單繪制幾行回论,并暫且注釋掉 K 線圖:
#candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
ax1.plot(date,closep)
ax1.plot(date,openp)
會(huì)生成:
已經(jīng)比默認(rèn)值好多了散罕!
樣式的另一個(gè)例子是fivethirtyeight
:
你可以這樣查看所有的可用樣式:
print(plt.style.available)
我這里它提供了['bmh', 'dark_background', 'ggplot', 'fivethirtyeight', 'grayscale']
。
讓我們嘗試dark_background
:
style.use('dark_background')
現(xiàn)在傀蓉,如果你想制作自己的風(fēng)格呢欧漱? 首先,你需要找到樣式目錄葬燎。 為了實(shí)現(xiàn)它误甚,如果你知道它在哪里,你可以前往你的 matplotlib 目錄谱净,或者你可以找到該目錄窑邦。 如果你不知道如何找到該目錄,你可以執(zhí)行以下操作:
print(plt.__file__)
這至少會(huì)告訴你pyplot
模塊的位置壕探。
在 matplotlib 目錄中冈钦,你需要尋找mpl-data
。 然后在那里李请,你需要尋找stylelib
瞧筛。 在 Windows 上 ,我的完整路徑是:C:\Python34\Lib\site-packages\matplotlib\mpl-data\stylelib
导盅。
那里應(yīng)該顯示了所有可用的.mplstyle
文件驾窟。 你可以編輯、復(fù)制或重命名它們认轨,然后在那里修改為你想要的東西。 然后月培,無論你用什么來命名.mplstyle
文件嘁字,都要放在style.use
中。
第十六章 實(shí)時(shí)圖表
在這篇 Matplotlib 教程中杉畜,我們將介紹如何創(chuàng)建實(shí)時(shí)更新圖表纪蜒,可以在數(shù)據(jù)源更新時(shí)更新其圖表。 你可能希望將此用于繪制股票實(shí)時(shí)定價(jià)數(shù)據(jù)此叠,或者可以將傳感器連接到計(jì)算機(jī)纯续,并且顯示傳感器實(shí)時(shí)數(shù)據(jù)。 為此灭袁,我們使用 Matplotlib 的動(dòng)畫功能猬错。
最開始:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
這里,唯一的新增導(dǎo)入是matplotlib.animation as animation
茸歧。 這是一個(gè)模塊倦炒,允許我們在顯示之后對圖形進(jìn)行動(dòng)畫處理。
接下來软瞎,我們添加一些你熟悉的代碼逢唤,如果你一直關(guān)注這個(gè)系列:
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
現(xiàn)在我們編寫動(dòng)畫函數(shù):
def animate(i):
graph_data = open('example.txt','r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x, y = line.split(',')
xs.append(x)
ys.append(y)
ax1.clear()
ax1.plot(xs, ys)
我們在這里做的是構(gòu)建數(shù)據(jù)拉讯,然后繪制它。 注意我們這里不調(diào)用plt.show()
鳖藕。 我們從一個(gè)示例文件讀取數(shù)據(jù)魔慷,其內(nèi)容如下:
1,5
2,3
3,4
4,7
5,4
6,3
7,5
8,7
9,4
10,4
我們打開上面的文件,然后存儲(chǔ)每一行著恩,用逗號(hào)分割成xs
和ys
院尔,我們將要繪制它。 然后:
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
我們運(yùn)行動(dòng)畫页滚,將動(dòng)畫放到圖表中(fig
)召边,運(yùn)行animate
的動(dòng)畫函數(shù),最后我們設(shè)置了 1000 的間隔裹驰,即 1000 毫秒或 1 秒隧熙。
運(yùn)行此圖表的結(jié)果應(yīng)該像往常一樣生成圖表。 然后幻林,你應(yīng)該能夠使用新的坐標(biāo)更新example.txt
文件贞盯。 這樣做會(huì)生成一個(gè)自動(dòng)更新的圖表,如下:
第十七章 注解和文本
在本教程中沪饺,我們將討論如何向 Matplotlib 圖形添加文本躏敢。 我們可以通過兩種方式來實(shí)現(xiàn)。 一種是將文本放置在圖表上的某個(gè)位置整葡。 另一個(gè)是專門注解圖表上的繪圖件余,來引起注意。
這里的起始代碼是教程 15遭居,它在這里:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.grid(True)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('ebay')
所以這里是 Yahoo Finance API 的 eBay 的 OHLC K 線圖啼器。 這里我們要講解的第一件事是向圖形添加文本。
font_dict = {'family':'serif',
'color':'darkred',
'size':15}
ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)
在這里俱萍,我們需要做一些事情端壳。 首先,我們使用ax1.text
添加文本枪蘑。 我們使用我們的數(shù)據(jù)损谦,以坐標(biāo)形式給出此文本的位置。 首先給出文本的坐標(biāo)岳颇,然后給出要放置的實(shí)際文本照捡。 接下來,我們使用fontdict
參數(shù)添加一個(gè)數(shù)據(jù)字典话侧,來使用所用的字體麻敌。 在我們的字體字典中,我們將字體更改為serif
掂摔,顏色為『深紅色』术羔,然后將字體大小更改為 15赢赊。這將全部應(yīng)用于我們的圖表上的文本,如下所示:
太棒了级历,接下來我們可以做的是释移,注解某個(gè)特定的繪圖。 我們希望這樣做來給出更多的信息寥殖。 在 eBay 的例子中玩讳,也許我們想解釋某個(gè)具體繪圖,或給出一些關(guān)于發(fā)生了什么的信息嚼贡。 在股價(jià)的例子中熏纯,也許有一些發(fā)生的新聞會(huì)影響價(jià)格。 你可以注解新聞來自哪里粤策,這將有助于解釋定價(jià)變化樟澜。
ax1.annotate('Bad News!',(date[9],highp[9]),
xytext=(0.8, 0.9), textcoords='axes fraction',
arrowprops = dict(facecolor='grey',color='grey'))
這里,我們用ax1.annotate
來注解叮盘。 我們首先傳遞我們想要注解的文本胎署,然后傳遞我們讓這個(gè)注解指向的坐標(biāo)霉咨。 我們這樣做他挎,是因?yàn)楫?dāng)我們注釋時(shí)牺陶,我們可以繪制線條和指向特定點(diǎn)的箭頭。 接下來愈魏,我們指定xytext
的位置觅玻。 它可以是像我們用于文本放置的坐標(biāo)位置,但是讓我們展示另一個(gè)例子培漏。 它可以為軸域小數(shù)串塑,所以我們使用 0.8 和 0.9。 這意味著文本的位置在x
軸的80%和y
軸的90%處北苟。 這樣,如果我們移動(dòng)圖表打瘪,文本將保持在相同位置友鼻。
執(zhí)行它,會(huì)生成:
根據(jù)你學(xué)習(xí)這個(gè)教程的時(shí)間闺骚,所指向的點(diǎn)可能有所不同彩扔,這只是一個(gè)注解的例子,其中有一些合理的想法僻爽,即為什么我們需要注解一些東西虫碉。
當(dāng)圖表啟動(dòng)時(shí),請嘗試單擊平移按鈕(藍(lán)色十字)胸梆,然后移動(dòng)圖表敦捧。 你會(huì)看到文本保持不動(dòng)须板,但箭頭跟隨移動(dòng)并繼續(xù)指向我們想要的具體的點(diǎn)。 這很酷吧兢卵!
最后一個(gè)圖表的完整代碼:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.grid(True)
ax1.annotate('Bad News!',(date[9],highp[9]),
xytext=(0.8, 0.9), textcoords='axes fraction',
arrowprops = dict(facecolor='grey',color='grey'))
## # Text placement example:
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
#plt.legend()
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('ebay')
現(xiàn)在习瑰,使用注解,我們可以做一些其他事情秽荤,如注解股票圖表的最后價(jià)格甜奄。 這就是我們接下來要做的。
第十八章 注解股票圖表的最后價(jià)格
在這個(gè) Matplotlib 教程中窃款,我們將展示如何跟蹤股票的最后價(jià)格的示例课兄,通過將其注解到軸域的右側(cè),就像許多圖表應(yīng)用程序會(huì)做的那樣晨继。
雖然人們喜歡在他們的實(shí)時(shí)圖表中看到歷史價(jià)格烟阐,他們也想看到最新的價(jià)格。 大多數(shù)應(yīng)用程序做的是踱稍,在價(jià)格的y
軸高度處注釋最后價(jià)格曲饱,然后突出顯示它,并在價(jià)格變化時(shí)珠月,在框中將其略微移動(dòng)扩淀。 使用我們最近學(xué)習(xí)的注解教程,我們可以添加一個(gè)bbox
啤挎。
我們的核心代碼是:
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
我們使用ax1.annotate
來放置最后價(jià)格的字符串值驻谆。 我們不在這里使用它,但我們將要注解的點(diǎn)指定為圖上最后一個(gè)點(diǎn)庆聘。 接下來胜臊,我們使用xytext
將我們的文本放置到特定位置。 我們將它的y
坐標(biāo)指定為最后一個(gè)點(diǎn)的y
坐標(biāo)伙判,x
坐標(biāo)指定為最后一個(gè)點(diǎn)的x
坐標(biāo)象对,再加上幾個(gè)點(diǎn)。我們這樣做是為了將它移出圖表宴抚。 將文本放在圖形外面就足夠了勒魔,但現(xiàn)在它只是一些浮動(dòng)文本。
我們使用bbox
參數(shù)在文本周圍創(chuàng)建一個(gè)框菇曲。 我們使用bbox_props
創(chuàng)建一個(gè)屬性字典冠绢,包含盒子樣式,然后是白色(w
)前景色常潮,黑色(k
)邊框顏色并且線寬為 1弟胀。 更多框樣式請參閱 matplotlib 注解文檔。
最后,這個(gè)注解向右移動(dòng)孵户,需要我們使用subplots_adjust
來創(chuàng)建一些新空間:
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.87, top=0.90, wspace=0.2, hspace=0)
這里的完整代碼如下:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+3, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax1.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
#plt.legend()
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.87, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
結(jié)果為:
第十九章 子圖
在這個(gè) Matplotlib 教程中萧朝,我們將討論子圖。 有兩種處理子圖的主要方法延届,用于在同一圖上創(chuàng)建多個(gè)圖表剪勿。 現(xiàn)在,我們將從一個(gè)干凈的代碼開始方庭。 如果你一直關(guān)注這個(gè)教程厕吉,那么請確保保留舊的代碼,或者你可以隨時(shí)重新查看上一個(gè)教程的代碼械念。
首先头朱,讓我們使用樣式,創(chuàng)建我們的圖表龄减,然后創(chuàng)建一個(gè)隨機(jī)創(chuàng)建示例繪圖的函數(shù):
import random
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')
fig = plt.figure()
def create_plots():
xs = []
ys = []
for i in range(10):
x = i
y = random.randrange(10)
xs.append(x)
ys.append(y)
return xs, ys
現(xiàn)在项钮,我們開始使用add_subplot
方法創(chuàng)建子圖:
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)
它的工作原理是使用 3 個(gè)數(shù)字,即:行數(shù)(numRows
)希停、列數(shù)(numCols
)和繪圖編號(hào)(plotNum
)烁巫。
所以,221 表示兩行兩列的第一個(gè)位置宠能。222 是兩行兩列的第二個(gè)位置亚隙。最后,212 是兩行一列的第二個(gè)位置违崇。
2x2:
+-----+-----+
| 1 | 2 |
+-----+-----+
| 3 | 4 |
+-----+-----+
2x1:
+-----------+
| 1 |
+-----------+
| 2 |
+-----------+
譯者注:原文此處表述有誤阿弃,譯文已更改。
譯者注:
221
是縮寫形式羞延,僅在行數(shù)乘列數(shù)小于 10 時(shí)有效渣淳,否則要寫成2,2,1
。
此代碼結(jié)果為:
這就是add_subplot
伴箩。 嘗試一些你認(rèn)為可能很有趣的配置入愧,然后嘗試使用add_subplot
創(chuàng)建它們,直到你感到滿意嗤谚。
接下來棺蛛,讓我們介紹另一種方法,它是subplot2grid
呵恢。
刪除或注釋掉其他軸域定義,然后添加:
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
所以媚创,add_subplot
不能讓我們使一個(gè)繪圖覆蓋多個(gè)位置渗钉。 但是這個(gè)新的subplot2grid
可以。 所以,subplot2grid
的工作方式是首先傳遞一個(gè)元組鳄橘,它是網(wǎng)格形狀声离。 我們傳遞了(6,1)
,這意味著整個(gè)圖表分為六行一列瘫怜。 下一個(gè)元組是左上角的起始點(diǎn)术徊。 對于ax1
,這是0,0
鲸湃,因此它起始于頂部赠涮。 接下來,我們可以選擇指定rowspan
和colspan
暗挑。 這是軸域所占的行數(shù)和列數(shù)笋除。
6x1:
colspan=1
(0,0) +-----------+
| ax1 | rowspan=1
(1,0) +-----------+
| |
| ax2 | rowspan=4
| |
| |
(5,0) +-----------+
| ax3 | rowspan=1
+-----------+
結(jié)果為:
顯然,我們在這里有一些重疊的問題炸裆,我們可以調(diào)整子圖來處理它垃它。
再次,嘗試構(gòu)思各種配置的子圖烹看,使用subplot2grid
制作出來国拇,直到你感到滿意!
我們將繼續(xù)使用subplot2grid
惯殊,將它應(yīng)用到我們已經(jīng)逐步建立的代碼中酱吝,我們將在下一個(gè)教程中繼續(xù)。
第二十章 將子圖應(yīng)用于我們的圖表
在這個(gè) Matplotlib 教程中靠胜,我們將處理我們以前教程的代碼掉瞳,并實(shí)現(xiàn)上一個(gè)教程中的子圖配置。 我們的起始代碼是這樣:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((1,1), (0,0))
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax1.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax1.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)
plt.xlabel('Date')
plt.ylabel('Price')
plt.title(stock)
#plt.legend()
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
一個(gè)主要的改動(dòng)是修改軸域的定義:
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
現(xiàn)在浪漠,ax2
是我們實(shí)際上在繪制的股票價(jià)格數(shù)據(jù)陕习。 頂部和底部圖表將作為指標(biāo)信息。
在我們繪制數(shù)據(jù)的代碼中址愿,我們需要將ax1
更改為ax2
:
candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax2.xaxis.get_ticklabels():
label.set_rotation(45)
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
更改之后该镣,代碼為:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax2.xaxis.get_ticklabels():
label.set_rotation(45)
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax1.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)
#
#plt.legend()
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
結(jié)果為:
第二十一章 更多指標(biāo)數(shù)據(jù)
在這篇 Matplotlib 教程中,我們介紹了添加一些簡單的函數(shù)來計(jì)算數(shù)據(jù)响谓,以便我們填充我們的軸域损合。 一個(gè)是簡單的移動(dòng)均值,另一個(gè)是簡單的價(jià)格 HML 計(jì)算娘纷。
這些新函數(shù)是:
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
你不需要太過專注于理解移動(dòng)均值的工作原理嫁审,我們只是對樣本數(shù)據(jù)來計(jì)算它,以便可以學(xué)習(xí)更多自定義 Matplotlib 的東西赖晶。
我們還想在腳本頂部為移動(dòng)均值定義一些值:
MA1 = 10
MA2 = 30
下面律适,在我們的graph_data
函數(shù)中:
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
在這里辐烂,我們計(jì)算兩個(gè)移動(dòng)均值和 HML。
我們還定義了一個(gè)『起始』點(diǎn)捂贿。 我們這樣做是因?yàn)槲覀兿M覀兊臄?shù)據(jù)排成一行纠修。 例如,20 天的移動(dòng)均值需要 20 個(gè)數(shù)據(jù)點(diǎn)厂僧。 這意味著我們不能在第 5 天真正計(jì)算 20 天的移動(dòng)均值扣草。 因此,當(dāng)我們計(jì)算移動(dòng)均值時(shí)颜屠,我們會(huì)失去一些數(shù)據(jù)辰妙。 為了處理這種數(shù)據(jù)的減法,我們使用起始變量來計(jì)算應(yīng)該有多少數(shù)據(jù)汽纤。 這里上岗,我們可以安全地使用[-start:]
繪制移動(dòng)均值,并且如果我們希望的話蕴坪,對所有繪圖進(jìn)行上述步驟來排列數(shù)據(jù)肴掷。
接下來,我們可以在ax1
上繪制 HML背传,通過這樣:
ax1.plot_date(date,h_l,'-')
最后我們可以通過這樣向ax3
添加移動(dòng)均值:
ax3.plot(date[-start:], ma1[-start:])
ax3.plot(date[-start:], ma2[-start:])
我們的完整代碼呆瞻,包括增加我們所用的時(shí)間范圍:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date,h_l,'-')
candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax2.xaxis.get_ticklabels():
label.set_rotation(45)
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax3.plot(date[-start:], ma1[-start:])
ax3.plot(date[-start:], ma2[-start:])
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
代碼效果如圖:
第二十二章 自定義填充、修剪和清除
歡迎閱讀另一個(gè) Matplotlib 教程径玖! 在本教程中痴脾,我們將清除圖表,然后再做一些自定義梳星。
我們當(dāng)前的代碼是:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date,h_l,'-')
candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
for label in ax2.xaxis.get_ticklabels():
label.set_rotation(45)
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax3.plot(date[-start:], ma1[-start:])
ax3.plot(date[-start:], ma2[-start:])
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
現(xiàn)在我認(rèn)為向我們的移動(dòng)均值添加自定義填充是一個(gè)很好的主意赞赖。 移動(dòng)均值通常用于說明價(jià)格趨勢。 這個(gè)想法是冤灾,你可以計(jì)算一個(gè)快速和一個(gè)慢速的移動(dòng)均值前域。 一般來說,移動(dòng)均值用于使價(jià)格變得『平滑』韵吨。 他們總是『滯后』于價(jià)格匿垄,但是我們的想法是計(jì)算不同的速度。 移動(dòng)均值越大就越『慢』归粉。 所以這個(gè)想法是椿疗,如果『較快』的移動(dòng)均值超過『較慢』的均值,那么價(jià)格就會(huì)上升糠悼,這是一件好事届榄。 如果較快的 MA 從較慢的 MA 下方穿過,則這是下降趨勢并且通常被視為壞事倔喂。 我的想法是在快速和慢速 MA 之間填充铝条,『上升』趨勢為綠色童擎,然后下降趨勢為紅色。 方法如下:
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
下面攻晒,我們會(huì)碰到一些我們可解決的問題:
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
這里,我們剪切和粘貼ax2
日期格式班挖,然后我們將x
刻度標(biāo)簽設(shè)置為false
鲁捏,去掉它們!
我們還可以通過在軸域定義中執(zhí)行以下操作萧芙,為每個(gè)軸域提供自定義標(biāo)簽:
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
接下來给梅,我們可以看到,我們y
刻度有許多數(shù)字双揪,經(jīng)扯穑互相覆蓋。 我們也看到軸之間互相重疊渔期。 我們可以這樣:
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='lower'))
所以运吓,這里發(fā)生的是,我們通過首先將nbins
設(shè)置為 5 來修改我們的y
軸對象疯趟。這意味著我們顯示的標(biāo)簽最多為 5 個(gè)拘哨。然后我們還可以『修剪』標(biāo)簽,因此信峻,在我們這里倦青, 我們修剪底部標(biāo)簽,這會(huì)使它消失盹舞,所以現(xiàn)在不會(huì)有任何文本重疊产镐。 我們?nèi)匀豢赡艽蛩阈藜?code>ax2的頂部標(biāo)簽,但這里是我們目前為止的源代碼:
當(dāng)前的源碼:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
plt.ylabel('MAvgs')
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date,h_l,'-')
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='lower'))
candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax3.plot(date[-start:], ma1[-start:], linewidth=1)
ax3.plot(date[-start:], ma2[-start:], linewidth=1)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
看起來好了一些踢步,但是仍然有一些東西需要清除癣亚。
第二十三章 共享 X 軸
在這個(gè) Matplotlib 數(shù)據(jù)可視化教程中,我們將討論sharex
選項(xiàng)贾虽,它允許我們在圖表之間共享x
軸逃糟。將sharex
看做『復(fù)制 x』也許更好。
在我們開始之前蓬豁,首先我們要做些修剪并在另一個(gè)軸上設(shè)置最大刻度數(shù)绰咽,如下所示:
ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
以及
ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))
現(xiàn)在,讓我們共享所有軸域之間的x
軸地粪。 為此取募,我們需要將其添加到軸域定義中:
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')
上面,對于ax2
和ax3
蟆技,我們添加一個(gè)新的參數(shù)玩敏,稱為sharex
斗忌,然后我們說,我們要與ax1
共享x
軸旺聚。
使用這種方式织阳,我們可以加載圖表薇缅,然后我們可以放大到一個(gè)特定的點(diǎn)攘蔽,結(jié)果將是這樣:
所以這意味著所有軸域沿著它們的x
軸一起移動(dòng)。 這很酷吧篡腌!
接下來碱璃,讓我們將[-start:]
應(yīng)用到所有數(shù)據(jù)弄痹,所以所有軸域都起始于相同地方。 我們最終的代碼為:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date[-start:],h_l[-start:],'-')
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))
candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax3.plot(date[-start:], ma1[-start:], linewidth=1)
ax3.plot(date[-start:], ma2[-start:], linewidth=1)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('EBAY')
下面我們會(huì)討論如何創(chuàng)建多個(gè)y
軸嵌器。
第二十四章 多個(gè) Y 軸
在這篇 Matplotlib 教程中肛真,我們將介紹如何在同一子圖上使用多個(gè) Y 軸。 在我們的例子中爽航,我們有興趣在同一個(gè)圖表及同一個(gè)子圖上繪制股票價(jià)格和交易量蚓让。
為此,首先我們需要定義一個(gè)新的軸域讥珍,但是這個(gè)軸域是ax2
僅帶有x
軸的『雙生子』凭疮。
這足以創(chuàng)建軸域了。我們叫它ax2v
串述,因?yàn)檫@個(gè)軸域是ax2
加交易量执解。
現(xiàn)在,我們在軸域上定義繪圖纲酗,我們將添加:
ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
我們在 0 和當(dāng)前交易量之間填充衰腌,給予它藍(lán)色的前景色,然后給予它一個(gè)透明度觅赊。 我們想要應(yīng)用幽冥毒右蕊,以防交易量最終覆蓋其它東西,所以我們?nèi)匀豢梢钥吹竭@兩個(gè)元素吮螺。
所以饶囚,到現(xiàn)在為止,我們的代碼為:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax2v = ax2.twinx()
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date[-start:],h_l[-start:],'-')
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))
candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
ax3.plot(date[-start:], ma1[-start:], linewidth=1)
ax3.plot(date[-start:], ma2[-start:], linewidth=1)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('GOOG')
會(huì)生成:
太棒了鸠补,到目前為止還不錯(cuò)萝风。 接下來,我們可能要?jiǎng)h除新y
軸上的標(biāo)簽紫岩,然后我們也可能不想讓交易量占用太多空間规惰。 沒問題:
首先:
ax2v.axes.yaxis.set_ticklabels([])
上面將y
刻度標(biāo)簽設(shè)置為一個(gè)空列表,所以不會(huì)有任何標(biāo)簽了泉蝌。
譯者注:所以將標(biāo)簽刪除之后歇万,添加新軸的意義是什么揩晴?直接在原軸域上繪圖就可以了。
接下來贪磺,我們可能要將網(wǎng)格設(shè)置為false
硫兰,使軸域上不會(huì)有雙網(wǎng)格:
ax2v.grid(False)
最后,為了處理交易量占用很多空間寒锚,我們可以做以下操作:
ax2v.set_ylim(0, 3*volume.max())
所以這設(shè)置y
軸顯示范圍從 0 到交易量的最大值的 3 倍瞄崇。 這意味著,在最高點(diǎn)壕曼,交易量最多可占據(jù)圖形的33%。 所以等浊,增加volume.max
的倍數(shù)越多腮郊,空間就越小/越少。
現(xiàn)在筹燕,我們的圖表為:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax2v = ax2.twinx()
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date[-start:],h_l[-start:],'-')
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))
candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+5, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
ax2v.axes.yaxis.set_ticklabels([])
ax2v.grid(False)
ax2v.set_ylim(0, 3*volume.max())
ax3.plot(date[-start:], ma1[-start:], linewidth=1)
ax3.plot(date[-start:], ma2[-start:], linewidth=1)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
plt.show()
graph_data('GOOG')
到這里轧飞,我們差不多完成了。 這里唯一的缺陷是一個(gè)好的圖例撒踪。 一些線條是顯而易見的过咬,但人們可能會(huì)好奇移動(dòng)均值的參數(shù)是什么,我們這里是 10 和 30制妄。 添加自定義圖例是下一個(gè)教程中涉及的內(nèi)容掸绞。
第二十五章 自定義圖例
在這篇 Matplotlib 教程中,我們將討論自定義圖例耕捞。 我們已經(jīng)介紹了添加圖例的基礎(chǔ)知識(shí)衔掸。
圖例的主要問題通常是圖例阻礙了數(shù)據(jù)的展示。 這里有幾個(gè)選項(xiàng)俺抽。 一個(gè)選項(xiàng)是將圖例放在軸域外敞映,但是我們在這里有多個(gè)子圖,這是非常困難的磷斧。 相反振愿,我們將使圖例稍微小一點(diǎn),然后應(yīng)用一個(gè)透明度弛饭。
首先冕末,為了創(chuàng)建一個(gè)圖例,我們需要向我們的數(shù)據(jù)添加我們想要顯示在圖例上的標(biāo)簽侣颂。
ax1.plot_date(date[-start:],h_l[-start:],'-', label='H-L')
...
ax2v.plot([],[], color='#0079a3', alpha=0.4, label='Volume')
...
ax3.plot(date[-start:], ma1[-start:], linewidth=1, label=(str(MA1)+'MA'))
ax3.plot(date[-start:], ma2[-start:], linewidth=1, label=(str(MA2)+'MA'))
請注意栓霜,我們通過創(chuàng)建空行為交易量添加了標(biāo)簽。 請記住横蜒,我們不能對任何填充應(yīng)用標(biāo)簽胳蛮,所以這就是我們添加這個(gè)空行的原因销凑。
現(xiàn)在,我們可以在右下角添加圖例仅炊,通過在plt.show()
之前執(zhí)行以下操作:
ax1.legend()
ax2v.legend()
ax3.legend()
會(huì)生成:
所以斗幼,我們可以看到,圖例還是占用了一些位置抚垄。 讓我們更改位置蜕窿,大小并添加透明度:
ax1.legend()
leg = ax1.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
ax2v.legend()
leg = ax2v.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
ax3.legend()
leg = ax3.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
所有的圖例位于位置 9(上中間)。 有很多地方可放置圖例呆馁,我們可以為參數(shù)傳入不同的位置號(hào)碼桐经,來看看它們都位于哪里。 ncol
參數(shù)允許我們指定圖例中的列數(shù)浙滤。 這里只有一列阴挣,如果圖例中有 2 個(gè)項(xiàng)目,他們將堆疊在一列中纺腊。 最后畔咧,我們將尺寸規(guī)定為更小。 之后揖膜,我們對整個(gè)圖例應(yīng)用0.4
的透明度誓沸。
現(xiàn)在我們的結(jié)果為:
完整的代碼為:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style
import numpy as np
import urllib
import datetime as dt
style.use('fivethirtyeight')
print(plt.style.available)
print(plt.__file__)
MA1 = 10
MA2 = 30
def moving_average(values, window):
weights = np.repeat(1.0, window)/window
smas = np.convolve(values, weights, 'valid')
return smas
def high_minus_low(highs, lows):
return highs-lows
def bytespdate2num(fmt, encoding='utf-8'):
strconverter = mdates.strpdate2num(fmt)
def bytesconverter(b):
s = b.decode(encoding)
return strconverter(s)
return bytesconverter
def graph_data(stock):
fig = plt.figure(facecolor='#f0f0f0')
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax2v = ax2.twinx()
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')
stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
split_line = line.split(',')
if len(split_line) == 6:
if 'values' not in line and 'labels' not in line:
stock_data.append(line)
date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
delimiter=',',
unpack=True,
converters={0: bytespdate2num('%Y%m%d')})
x = 0
y = len(date)
ohlc = []
while x < y:
append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
ohlc.append(append_me)
x+=1
ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])
h_l = list(map(high_minus_low, highp, lowp))
ax1.plot_date(date[-start:],h_l[-start:],'-', label='H-L')
ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))
candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
ax2.grid(True)
bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)
## # Annotation example with arrow
## ax2.annotate('Bad News!',(date[11],highp[11]),
## xytext=(0.8, 0.9), textcoords='axes fraction',
## arrowprops = dict(facecolor='grey',color='grey'))
##
##
## # Font dict example
## font_dict = {'family':'serif',
## 'color':'darkred',
## 'size':15}
## # Hard coded text
## ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
ax2v.plot([],[], color='#0079a3', alpha=0.4, label='Volume')
ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
ax2v.axes.yaxis.set_ticklabels([])
ax2v.grid(False)
ax2v.set_ylim(0, 3*volume.max())
ax3.plot(date[-start:], ma1[-start:], linewidth=1, label=(str(MA1)+'MA'))
ax3.plot(date[-start:], ma2[-start:], linewidth=1, label=(str(MA2)+'MA'))
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] < ma2[-start:]),
facecolor='r', edgecolor='r', alpha=0.5)
ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
where=(ma1[-start:] > ma2[-start:]),
facecolor='g', edgecolor='g', alpha=0.5)
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))
for label in ax3.xaxis.get_ticklabels():
label.set_rotation(45)
plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)
plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
ax1.legend()
leg = ax1.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
ax2v.legend()
leg = ax2v.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
ax3.legend()
leg = ax3.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)
plt.show()
fig.savefig('google.png', facecolor=fig.get_facecolor())
graph_data('GOOG')
現(xiàn)在我們可以看到圖例,但也看到了圖例下的任何信息壹粟。 還要注意額外函數(shù)fig.savefig
拜隧。 這是自動(dòng)保存圖形的圖像的方式。 我們還可以設(shè)置所保存的圖形的前景色趁仙,使背景不是白色的虹蓄,如我們的例子所示。
這就是目前為止幸撕,我想要顯示的典型 Matplotlib 圖表薇组。 接下來,我們將涉及Basemap
坐儿,它是一個(gè) Matplotlib 擴(kuò)展律胀,用于繪制地理位置,然后我打算講解 Matplotlib 中的 3D 圖形貌矿。
第二十六章 Basemap 地理繪圖
在這個(gè) Matplotlib 教程中炭菌,我們將涉及地理繪圖模塊Basemap
。 Basemap
是 Matplotlib 的擴(kuò)展逛漫。
為了使用Basemap
黑低,我們首先需要安裝它。 為了獲得Basemap
,你可以從這里獲瓤宋铡:http://matplotlib.org/basemap/users/download.html蕾管,或者你可以訪問http://www.lfd.uci.edu/~gohlke/pythonlibs/。
如果你在安裝Basemap
時(shí)遇到問題菩暗,請查看pip
安裝教程掰曾。
一旦你安裝了Basemap
,你就可以創(chuàng)建地圖了停团。 首先旷坦,讓我們投影一個(gè)簡單的地圖。 為此佑稠,我們需要導(dǎo)入Basemap
秒梅,pyplot
,創(chuàng)建投影舌胶,至少繪制某種輪廓或數(shù)據(jù)捆蜀,然后我們可以顯示圖形。
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill')
m.drawcoastlines()
plt.show()
上面的代碼結(jié)果如下:
這是使用 Miller 投影完成的辆琅,這只是許多Basemap
投影選項(xiàng)之一。
第二十七章 Basemap 自定義
在這篇 Matplotlib 教程中这刷,我們繼續(xù)使用Basemap
地理繪圖擴(kuò)展婉烟。 我們將展示一些我們可用的自定義選項(xiàng)。
首先暇屋,從上一個(gè)教程中獲取我們的起始代碼:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill')
m.drawcoastlines()
plt.show()
我們可以從放大到特定區(qū)域來開始:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill',
llcrnrlat = -40,
llcrnrlon = -40,
urcrnrlat = 50,
urcrnrlon = 75)
m.drawcoastlines()
plt.show()
這里的參數(shù)是:
-
llcrnrlat
- 左下角的緯度 -
llcrnrlon
- 左下角的經(jīng)度 -
urcrnrlat
- 右上角的緯度 -
urcrnrlon
- 右上角的經(jīng)度
此外似袁,坐標(biāo)需要轉(zhuǎn)換,其中西經(jīng)和南緯坐標(biāo)是負(fù)值咐刨,北緯和東經(jīng)坐標(biāo)是正值昙衅。
使用這些坐標(biāo),Basemap
會(huì)選擇它們之間的區(qū)域定鸟。
下面而涉,我們要使用一些東西,類似:
m.drawcountries(linewidth=2)
這會(huì)畫出國家联予,并使用線寬為 2 的線條生成分界線啼县。
另一個(gè)選項(xiàng)是:
m.drawstates(color='b')
這會(huì)用藍(lán)色線條畫出州。
你也可以執(zhí)行:
m.drawcounties(color='darkred')
這會(huì)畫出國家沸久。
所以季眷,我們的代碼是:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill',
llcrnrlat = -90,
llcrnrlon = -180,
urcrnrlat = 90,
urcrnrlon = 180)
m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')
m.drawcounties(color='darkred')
plt.title('Basemap Tutorial')
plt.show()
很難說,但我們定義了美國的區(qū)縣的線條卷胯。 我們可以使用放大鏡放大Basemap
圖形子刮,就像其他圖形那樣,會(huì)生成:
另一個(gè)有用的選項(xiàng)是Basemap
調(diào)用中的『分辨率』選項(xiàng)窑睁。
m = Basemap(projection='mill',
llcrnrlat = -90,
llcrnrlon = -180,
urcrnrlat = 90,
urcrnrlon = 180,
resolution='l')
分辨率的選項(xiàng)為:
-
c
- 粗糙 -
l
- 低 -
h
- 高 -
f
- 完整
對于更高的分辨率挺峡,你應(yīng)該放大到很大葵孤,否則這可能只是浪費(fèi)。
另一個(gè)選項(xiàng)是使用etopo()
繪制地形沙郭,如:
m.etopo()
使用drawcountries
方法繪制此圖形會(huì)生成:
最后佛呻,有一個(gè)藍(lán)色的大理石版本,你可以調(diào)用:
m.bluemarble()
會(huì)生成:
目前為止的代碼:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill',
llcrnrlat = -90,
llcrnrlon = -180,
urcrnrlat = 90,
urcrnrlon = 180,
resolution='l')
m.drawcoastlines()
m.drawcountries(linewidth=2)
##m.drawstates(color='b')
##m.drawcounties(color='darkred')
#m.fillcontinents()
#m.etopo()
m.bluemarble()
plt.title('Basemap Tutorial')
plt.show()
第二十八章 在 Basemap 中繪制坐標(biāo)
歡迎閱讀另一個(gè) Matplotlib Basemap 教程病线。 在本教程中吓著,我們將介紹如何繪制單個(gè)坐標(biāo),以及如何在地理區(qū)域中連接這些坐標(biāo)送挑。
首先绑莺,我們將從一些基本的起始數(shù)據(jù)開始:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill',
llcrnrlat = 25,
llcrnrlon = -130,
urcrnrlat = 50,
urcrnrlon = -60,
resolution='l')
m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')
接下來,我們可以繪制坐標(biāo)惕耕,從獲得它們的實(shí)際坐標(biāo)開始纺裁。 記住,南緯和西經(jīng)坐標(biāo)需要轉(zhuǎn)換為負(fù)值司澎。 例如欺缘,紐約市是北緯40.7127
西經(jīng)74.0059
。 我們可以在我們的程序中定義這些坐標(biāo)挤安,如:
NYClat, NYClon = 40.7127, -74.0059
之后我們將這些轉(zhuǎn)換為要繪制的x
和y
坐標(biāo)谚殊。
xpt, ypt = m(NYClon, NYClat)
注意這里,我們現(xiàn)在已經(jīng)將坐標(biāo)順序翻轉(zhuǎn)為lon, lat
(緯度蛤铜,經(jīng)度)嫩絮。 坐標(biāo)通常以lat, lon
順序給出。 然而围肥,在圖形中剿干,lat, long
轉(zhuǎn)換為y, x
,我們顯然不需要穆刻。 在某些時(shí)候置尔,你必須翻轉(zhuǎn)它們。 不要忘記這部分氢伟!
最后撰洗,我們可以繪制如下的坐標(biāo):
m.plot(xpt, ypt, 'c*', markersize=15)
這個(gè)圖表上有一個(gè)青色的星,大小為 15腐芍。更多標(biāo)記類型請參閱:Matplotlib 標(biāo)記文檔差导。
接下來,讓我們再畫一個(gè)位置猪勇,洛杉磯设褐,加利福尼亞:
LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
m.plot(xpt, ypt, 'g^', markersize=15)
這次我們畫出一個(gè)綠色三角,執(zhí)行代碼會(huì)生成:
如果我們想連接這些圖塊怎么辦?原來助析,我們可以像其它 Matplotlib 圖表那樣實(shí)現(xiàn)它犀被。
首先,我們將那些xpt
和ypt
坐標(biāo)保存到列表外冀,類似這樣的東西:
xs = []
ys = []
NYClat, NYClon = 40.7127, -74.0059
xpt, ypt = m(NYClon, NYClat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'c*', markersize=15)
LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'g^', markersize=15)
m.plot(xs, ys, color='r', linewidth=3, label='Flight 98')
會(huì)生成:
太棒了寡键。有時(shí)我們需要以圓弧連接圖上的兩個(gè)坐標(biāo)。如何實(shí)現(xiàn)呢雪隧?
m.drawgreatcircle(NYClon, NYClat, LAlon, LAlat, color='c', linewidth=3, label='Arc')
我們的完整代碼為:
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
m = Basemap(projection='mill',
llcrnrlat = 25,
llcrnrlon = -130,
urcrnrlat = 50,
urcrnrlon = -60,
resolution='l')
m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')
#m.drawcounties(color='darkred')
#m.fillcontinents()
#m.etopo()
#m.bluemarble()
xs = []
ys = []
NYClat, NYClon = 40.7127, -74.0059
xpt, ypt = m(NYClon, NYClat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'c*', markersize=15)
LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'g^', markersize=15)
m.plot(xs, ys, color='r', linewidth=3, label='Flight 98')
m.drawgreatcircle(NYClon, NYClat, LAlon, LAlat, color='c', linewidth=3, label='Arc')
plt.legend(loc=4)
plt.title('Basemap Tutorial')
plt.show()
結(jié)果為:
這就是Basemap
的全部了西轩,下一章關(guān)于 Matplotlib 的 3D 繪圖。
第二十九章 3D 繪圖
您好脑沿,歡迎閱讀 Matplotlib 教程中的 3D 繪圖藕畔。 Matplotlib 已經(jīng)內(nèi)置了三維圖形,所以我們不需要再下載任何東西庄拇。 首先注服,我們需要引入一些完整的模塊:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
使用axes3d
是因?yàn)樗枰煌N類的軸域,以便在三維中實(shí)際繪制一些東西措近。 下面:
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
在這里溶弟,我們像通常一樣定義圖形,然后我們將ax1
定義為通常的子圖瞭郑,只是這次使用 3D 投影辜御。 我們需要這樣做,以便提醒 Matplotlib 我們要提供三維數(shù)據(jù)凰浮。
現(xiàn)在讓我們創(chuàng)建一些 3D 數(shù)據(jù):
x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]
接下來我抠,我們繪制它苇本。 首先袜茧,讓我們展示一個(gè)簡單的線框示例:
ax1.plot_wireframe(x,y,z)
最后:
ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')
plt.show()
我們完整的代碼是:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]
ax1.plot_wireframe(x,y,z)
ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')
plt.show()
結(jié)果為(包括所用的樣式):
這些 3D 圖形可以進(jìn)行交互。 首先瓣窄,您可以使用鼠標(biāo)左鍵單擊并拖動(dòng)來移動(dòng)圖形笛厦。 您還可以使用鼠標(biāo)右鍵單擊并拖動(dòng)來放大或縮小。
第三十章 3D 散點(diǎn)圖
歡迎閱讀另一個(gè) 3D Matplotlib 教程俺夕,會(huì)涉及如何繪制三維散點(diǎn)圖裳凸。
繪制 3D 散點(diǎn)圖非常類似于通常的散點(diǎn)圖以及 3D 線框圖。
一個(gè)簡單示例:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]
x2 = [-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
y2 = [-5,-6,-7,-8,-2,-5,-6,-3,-7,-2]
z2 = [1,2,6,3,2,7,3,3,7,2]
ax1.scatter(x, y, z, c='g', marker='o')
ax1.scatter(x2, y2, z2, c ='r', marker='o')
ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')
plt.show()
結(jié)果為:
要記住你可以修改這些繪圖的大小和標(biāo)記劝贸,就像通常的散點(diǎn)圖那樣姨谷。
第三十一章 3D 條形圖
在這個(gè) Matplotlib 教程中,我們要介紹 3D 條形圖映九。 3D 條形圖是非常獨(dú)特的梦湘,因?yàn)樗试S我們繪制多于 3 個(gè)維度。 不,你不能超過第三個(gè)維度來繪制捌议,但你可以繪制多于 3 個(gè)維度哼拔。
對于條形圖,你需要擁有條形的起點(diǎn)瓣颅,條形的高度和寬度倦逐。 但對于 3D 條形圖,你還有另一個(gè)選項(xiàng)宫补,就是條形的深度檬姥。 大多數(shù)情況下,條形圖從軸上的條形平面開始守谓,但是你也可以通過打破此約束來添加另一個(gè)維度穿铆。 然而,我們會(huì)讓它非常簡單:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import style
style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x3 = [1,2,3,4,5,6,7,8,9,10]
y3 = [5,6,7,8,2,5,6,3,7,2]
z3 = np.zeros(10)
dx = np.ones(10)
dy = np.ones(10)
dz = [1,2,3,4,5,6,7,8,9,10]
ax1.bar3d(x3, y3, z3, dx, dy, dz)
ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')
plt.show()
注意這里斋荞,我們必須定義x
荞雏、y
和z
,然后是 3 個(gè)維度的寬度平酿、高度和深度凤优。 這會(huì)生成:
第三十二章 總結(jié)
歡迎閱讀最后的 Matplotlib 教程。 在這里我們將整理整個(gè)系列蜈彼,并顯示一個(gè)稍微更復(fù)雜的 3D 線框圖:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import style
style.use('ggplot')
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
x, y, z = axes3d.get_test_data()
print(axes3d.__file__)
ax1.plot_wireframe(x,y,z, rstride = 3, cstride = 3)
ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')
plt.show()
如果你從一開始就關(guān)注這個(gè)教程的話筑辨,那么你已經(jīng)學(xué)會(huì)了 Matplotlib 提供的大部分內(nèi)容。 你可能不相信幸逆,但Matplotlib 仍然可以做很多其他的事情棍辕! 請繼續(xù)學(xué)習(xí),你可以隨時(shí)訪問 Matplotlib.org还绘,并查看示例和圖庫頁面楚昭。
如果你發(fā)現(xiàn)自己大量使用 Matplotlib,請考慮捐助給 John Hunter Memorial 基金拍顷。
注:空間曲面的畫法
# 二次拋物面 z = x^2 + y^2 x = np.linspace(-10, 10, 101) y = x x, y = np.meshgrid(x, y) z = x ** 2 + y ** 2 ax = plot.subplot(111, projection='3d') ax.plot_wireframe(x, y, z) plot.show()
# 半徑為 1 的球 t = np.linspace(0, np.pi * 2, 100) s = np.linspace(0, np.pi, 100) t, s = np.meshgrid(t, s) x = np.cos(t) * np.sin(s) y = np.sin(t) * np.sin(s) z = np.cos(s) ax = plot.subplot(111, projection='3d') ax.plot_wireframe(x, y, z) plot.show()