• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Python 數據科學入門教程:Matplotlib

    Matplotlib 入門教程

    來源:Introduction to Matplotlib and basic line

    譯者:飛龍

    協議:CC BY-NC-SA 4.0

    第一章 Matplotlib 簡介

    歡迎閱讀 Python 3+ Matplotlib 系列教程。 在本系列中,我們將涉及 Matplotlib 數據可視化模塊的多個方面。 Matplotlib 能夠創建多數類型的圖表,如條形圖,散點圖,條形圖,餅圖,堆疊圖,3D 圖和地圖圖表。

    首先,為了實際使用 Matplotlib,我們需要安裝它。

    如果你安裝了更高版本的 Python,你應該能夠打開cmd.exe或終端,然后執行:

    pip install matplotlib

    注意:如果上面的較短命令不工作,你可能需要執行C:/Python34/Scripts/pip install matplotlib

    如果在導入matplotlib時,你會收到類似『無命名模塊』和模塊名稱的錯誤,這意味著你還需要安裝該模塊。 一個常見的問題是缺少名為six的模塊。 這意味著你需要使用pip安裝six

    或者,你可以前往 Matplotlib.org 并通過訪問下載頁面下載適當的版本進行安裝。 請記住,因為你的操作系統為 64 位,你不一定需要 64 位版本的 Python。 如果你不打算嘗試 64 位,你可以使用 32 位。 打開 IDLE 并閱讀頂部。 如果它說你是 64 位,你就是 64 位,如果它說是 32 位,那么你就是 32 位。 一旦你安裝了 Python,你就做好了準備,你可以編寫任何你想要的邏輯。 我喜歡使用 IDLE 來編程,但你可以隨意使用任何你喜歡的東西。

    import matplotlib.pyplot as plt

    這一行導入集成的pyplot,我們將在整個系列中使用它。 我們將pyplot導入為plt,這是使用pylot的 python 程序的傳統慣例。

    plt.plot([1,2,3],[5,7,4])

    接下來,我們調用plot.plot方法繪制一些坐標。 這個.plot需要許多參數,但前兩個是'x''y'坐標,我們放入列表。 這意味著,根據這些列表我們擁有 3 個坐標:1,5 2,73,4

    plt.plot在后臺『繪制』這個繪圖,但繪制了我們想要的一切之后,當我們準備好的時候,我們需要把它帶到屏幕上。

    plt.show()

    這樣,應該彈出一個圖形。 如果沒有,有時它可以彈出,或者你可能得到一個錯誤。 你的圖表應如下所示:

    這個窗口是一個 matplotlib 窗口,它允許我們查看我們的圖形,以及與它進行交互和訪問。 你可以將鼠標懸停在圖表上,并查看通常在右下角的坐標。 你也可以使用按鈕。 它們可能在不同的位置,但在上圖中,這些按鈕在左下角。

    Home(主頁)

    一旦你開始瀏覽你的圖表,主頁按鈕會幫助你。 如果你想要返回原始視圖,可以單擊它。 在瀏覽圖表之前單擊此按鈕將不會生效。

    Forward/Back(前進/后退)

    這些按鈕可以像瀏覽器中的前進和后退按鈕一樣使用。 你可以單擊這些來移回到你之前的位置,或再次前進。

    Pan(平移)

    你可以點擊平移按鈕,之后點擊并拖拽你的圖表。

    Zoom(縮放)

    縮放按鈕可讓你單擊它,然后單擊并拖動出要放大的方形區域。 放大需要左鍵單擊并拖動。 你也可以右鍵單擊并拖動來縮小。

    Configure Subplots(配置子圖)

    此按鈕允許你對圖形和繪圖配置各種間距選項。 點擊它會彈出:

    每個藍色條形都是一個滑塊,它允許你調整內邊距。 其中有些現在沒有任何效果,因為沒有任何其他子圖。 前四個值調整圖形到窗口邊緣的邊距。 之后wspacehspace對應于當你繪制多個子圖時,它們的水平或豎直間距。

    Save(保存)

    此按鈕允許你以各種形式保存圖形。

    所以這是 matplotlib 的快速介紹,我們之后會涉及更多。

    第二章 圖例、標題和標簽

    在本教程中,我們將討論 Matplotlib 中的圖例,標題和標簽。 很多時候,圖形可以不言自明,但是圖形帶有標題,軸域上的標簽和圖例,來解釋每一行是什么非常必要。

    注:軸域(Axes)即兩條坐標軸圍城的區域。

    從這里開始:

    import matplotlib.pyplot as plt
    
    x = [1,2,3]
    y = [5,7,4]
    
    x2 = [1,2,3]
    y2 = [10,14,12]

    這樣我們可以畫出兩個線條,接下來:

    plt.plot(x, y, label='First Line')
    plt.plot(x2, y2, label='Second Line')

    在這里,我們繪制了我們已經看到的東西,但這次我們添加另一個參數label。 這允許我們為線條指定名稱,我們以后可以在圖例中顯示它。 我們的其余代碼為:

    plt.xlabel('Plot Number')
    plt.ylabel('Important var')
    plt.title('Interesting Graph\nCheck it out')
    plt.legend()
    plt.show()

    使用plt.xlabelplt.ylabel,我們可以為這些相應的軸創建標簽。 接下來,我們可以使用plt.title創建圖的標題,然后我們可以使用plt.legend()生成默認圖例。 結果圖如下:

    第三章 條形圖和直方圖

    這個教程中我們會涉及條形圖和直方圖。我們先來看條形圖:

    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為我們創建條形圖。 如果你沒有明確選擇一種顏色,那么雖然做了多個圖,所有的條看起來會一樣。 這讓我們有機會使用一個新的 Matplotlib 自定義選項。 你可以在任何類型的繪圖中使用顏色,例如g為綠色,b為藍色,r為紅色,等等。 你還可以使用十六進制顏色代碼,如#191970

    接下來,我們會講解直方圖。 直方圖非常像條形圖,傾向于通過將區段組合在一起來顯示分布。 這個例子可能是年齡的分組,或測試的分數。 我們并不是顯示每一組的年齡,而是按照 20 ~ 25,25 ~ 30… 等等來顯示年齡。 這里有一個例子:

    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()

    產生的圖表為:

    對于plt.hist,你首先需要放入所有的值,然后指定放入哪個桶或容器。 在我們的例子中,我們繪制了一堆年齡,并希望以 10 年的增量來顯示它們。 我們將條形的寬度設為 0.8,但是如果你想讓條形變寬,或者變窄,你可以選擇其他的寬度。

    第四章 散點圖

    接下來,我們將介紹散點圖。散點圖通常用于比較兩個變量來尋找相關性或分組,如果你在 3 維繪制則是 3 個。

    散點圖的一些示例代碼:

    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()

    結果為:

    plt.scatter不僅允許我們繪制xy,而且還可以讓我們決定所使用的標記顏色,大小和類型。 有一堆標記選項,請參閱 Matplotlib 標記文檔中的所有選項。

    第五章 堆疊圖

    在這篇 Matplotlib 數據可視化教程中,我們要介紹如何創建堆疊圖。 堆疊圖用于顯示『部分對整體』隨時間的關系。 堆疊圖基本上類似于餅圖,只是隨時間而變化。

    讓我們考慮一個情況,我們一天有 24 小時,我們想看看我們如何花費時間。 我們將我們的活動分為:睡覺,吃飯,工作和玩耍。

    我們假設我們要在 5 天的時間內跟蹤它,因此我們的初始數據將如下所示:

    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。然后,日期的各個成分保存在它們各自的活動中。 像這樣繪制它們:

    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()

    在這里,我們可以至少在顏色上看到,我們如何花費我們的時間。 問題是,如果不回頭看代碼,我們不知道什么顏色是什么。 下一個問題是,對于多邊形來說,我們實際上不能為數據添加『標簽』。 因此,在任何不止是線條,帶有像這樣的填充或堆疊圖的地方,我們不能以固有方式標記出特定的部分。 這不應該阻止程序員。 我們可以解決這個問題:

    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()

    我們在這里做的是畫一些空行,給予它們符合我們的堆疊圖的相同顏色,和正確標簽。 我們還使它們線寬為 5,使線條在圖例中顯得較寬。 現在,我們可以很容易地看到,我們如何花費我們的時間。

    第六章 餅圖

    餅圖很像堆疊圖,只是它們位于某個時間點。 通常,餅圖用于顯示部分對于整體的情況,通常以%為單位。 幸運的是,Matplotlib 會處理切片大小以及一切事情,我們只需要提供數值。

    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中,我們需要指定『切片』,這是每個部分的相對大小。 然后,我們指定相應切片的顏色列表。 接下來,我們可以選擇指定圖形的『起始角度』。 這使你可以在任何地方開始繪圖。 在我們的例子中,我們為餅圖選擇了 90 度角,這意味著第一個部分是一個豎直線條。 接下來,我們可以選擇給繪圖添加一個字符大小的陰影,然后我們甚至可以使用explode拉出一個切片。

    我們總共有四個切片,所以對于explode,如果我們不想拉出任何切片,我們傳入0,0,0,0。 如果我們想要拉出第一個切片,我們傳入0.1,0,0,0

    最后,我們使用autopct,選擇將百分比放置到圖表上面。

    第七章 從文件加載數據

    很多時候,我們想要繪制文件中的數據。 有許多類型的文件,以及許多方法,你可以使用它們從文件中提取數據來圖形化。 在這里,我們將展示幾種方法。 首先,我們將使用內置的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()

    這里,我們打開樣例文件,包含以下數據:

    1,5
    2,3
    3,4
    4,7
    5,4
    6,3
    7,5
    8,7
    9,4
    10,4

    接下來,我們使用csv模塊讀取數據。 csv讀取器自動按行分割文件,然后使用我們選擇的分隔符分割文件中的數據。 在我們的例子中,這是一個逗號。 注意:csv模塊和csv reader不需要文件在字面上是一個.csv文件。 它可以是任何具有分隔數據的簡單的文本文件。

    一旦我們這樣做了,我們將索引為 0 的元素存儲到x列表,將索引為 1 的元素存儲到y列表中。 之后,我們都設置好了,準備繪圖,然后顯示數據。

    雖然使用 CSV 模塊是完全正常的,但使用 NumPy 模塊來加載我們的文件和數據,可能對我們更有意義。 如果你沒有 NumPy,你需要按下面的步驟來獲取它。 為了了解安裝模塊的更多信息,請參閱 pip 教程。 大多數人應該都能打開命令行,并執行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()

    結果應該是相同的圖表。 稍后,當我們加載數據時,我們可以利用 NumPy 為我們做一些更多的工作,但這是教程未來的內容。 就像csv模塊不需要一個特地的.csv一樣,loadtxt函數不要求文件是一個.txt文件,它可以是一個.csv,它甚至可以是一個 python 列表對象。

    第八章 從網絡加載數據

    除了從文件加載數據,另一個流行的數據源是互聯網。 我們可以用各種各樣的方式從互聯網加載數據,但對我們來說,我們只是簡單地讀取網站的源代碼,然后通過簡單的拆分來分離數據。

    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)

    這里有很多步驟。首先,我們看到importpyplot像往常一樣導入,然后導入了numpy,然后是用于訪問互聯網的urllib,然后導入了matplotlib.dates作為mdates,它對于將日期戳轉換為 matplotlib 可以理解的日期很有用。

    接下來,我們開始構建我們的graph_data函數。在這里,我們首先定義包含股票數據的網址。之后,我們寫一些urllib代碼來訪問該 URL,然后使用.read讀取源代碼,之后我們繼續解碼該數據。如果你使用 Python 2,則不必使用decode

    然后,我們定義一個空列表,這是我們將要放置股票數據的地方,我們也開始使用split_source變量拆分數據,以換行符拆分。

    現在,如果你去看源代碼,用stock替換 URL 中的+stock+,像 AAPL 那樣,你可以看到大多數頁面數據確實是股票定價信息,但有一些頭信息我們需要過濾掉。為此,我們使用一些基本的過濾,檢查它們來確保每行有 6 個數據點,然后確保術語values不在行中。

    現在,我們已經解析了數據,并做好了準備。我們將使用 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')})

    我們在這里所做的是,使用numpyloadtxt函數,并將這六個元素解構到六個變量。 這里的第一個參數是stock_data,這是我們加載的數據。 然后,我們指定delimiter(這里是逗號),然后我們指定我們確實想要在這里解包變量,不是一個變量,而是我們定義的這組變量。 最后,我們使用可選的converters參數來指定我們要轉換的元素(0),以及我們打算要怎么做。 我們傳遞一個名為bytespdate2num的函數,它還不存在,但我們下面會編寫它。

    第九章 時間戳的轉換

    本教程的重點是將來自 Yahoo finance API 的日期轉換為 Matplotlib 可理解的日期。 為了實現它,我們要寫一個新的函數,bytespdate2num

    def bytespdate2num(fmt, encoding='utf-8'):
        strconverter = mdates.strpdate2num(fmt)
        def bytesconverter(b):
            s = b.decode(encoding)
            return strconverter(s)
        return bytesconverter

    此函數接受數據,基于編碼來解碼數據,然后返回它。

    將此應用于我們的程序的其余部分:

    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,結果圖應該看起來像這樣:

    第十章 基本的自定義

    在 Matplotlib 教程中,我們將討論一些可能的圖表自定義。 為了開始修改子圖,我們必須定義它們。 我們很快會談論他們,但有兩種定義并構造子圖的主要方法。 現在,我們只使用其中一個,但我們會很快解釋它們。

    現在,修改我們的graph_data函數:

    def graph_data(stock):
    
        fig = plt.figure()
        ax1 = plt.subplot2grid((1,1), (0,0))

    為了修改圖表,我們需要引用它,所以我們將它存儲到變量fig。 然后我們將ax1定義為圖表上的子圖。 我們在這里使用subplot2grid,這是獲取子圖的兩種主要方法之一。 我們將深入討論這些東西,但現在,你應該看到我們有 2 個元組,它們提供了(1,1)(0,0)1,1表明這是一個 1×1 網格。 然后0,0表明這個子圖的『起點』將為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)

    然后,其它東西我們保留默認,但我們也可能需要略微調整繪圖,因為日期跑到了圖表外面。 記不記得我們在第一篇教程中討論的configure subplots按鈕? 我們不僅可以以這種方式配置圖表,我們還可以在代碼中配置它們,以下是我們設置這些參數的方式:

    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)

    現在,為了防止我們把你遺留在某個地方,這里是完整的代碼:

    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')

    結果為:

    第十一章 Unix 時間

    在這個 Matplotlib 教程中,我們將介紹如何處理 unix 時間戳的轉換,然后在圖形中繪制日期戳。 使用 Yahoo Finance API,你會注意到,如果你使用較大的時間間隔,如1y(一年),你會得到我們一直在使用的日期戳,但如果你使用10d(10 天),反之你會得到 unix 時間的時間戳。

    Unix 時間是 1970 年 1 月 1 日以后的秒數,它是跨程序的標準化時間表示方法。 也就是說,Matplotlib 并不歡迎 unix 時間戳。 這里是你可以使用 Matplotlib 來處理 unix 時間的方式:

    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 時間的寫入處理,并注釋掉我們以前的代碼,因為我們為之后的使用而保存它。 這里的主要區別是:

    dateconv = np.vectorize(dt.datetime.fromtimestamp)
    date = dateconv(date)

    這里,我們將時間戳轉換為日期戳,然后將其轉換為 Matplotlib 想要的時間。

    現在,由于某些原因,我的 unix 時間帶有另一行包含 6 個元素的數據,并且它包含了術語label,因此,在我們解析數據的for循環中,我們為你再添加一個需要注意的檢查:

    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)

    現在你的圖表應該類似:

    這里的所有扁平線條的原因是市場關閉。 有了這個短期數據,我們可以得到日內數據。 所以交易開放時有很多點,然后市場關閉時就沒有了,然后又是一堆,然后又是沒有。

    第十二章 顏色和填充

    在本教程中,我們將介紹一些更多的自定義,比如顏色和線條填充。

    我們要做的第一個改動是將plt.title更改為stock變量。

    plt.title(stock)

    現在,讓我們來介紹一下如何更改標簽顏色。 我們可以通過修改我們的軸對象來實現:

    ax1.xaxis.label.set_color('c')
    ax1.yaxis.label.set_color('r')

    如果我們運行它,我們會看到標簽改變了顏色,就像在單詞中那樣。

    接下來,我們可以為要顯示的軸指定具體數字,而不是像這樣的自動選擇:

    ax1.set_yticks([0,25,50,75])

    接下來,我想介紹填充。 填充所做的事情,是在變量和你選擇的一個數值之間填充顏色。 例如,我們可以這樣:

    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')

    結果為:

    填充的一個問題是,我們可能最后會把東西都覆蓋起來。 我們可以用透明度來解決它:

    ax1.fill_between(date, 0, closep)

    現在,讓我們介紹條件填充。 讓我們假設圖表的起始位置是我們開始買入 eBay 的地方。 這里,如果價格低于這個價格,我們可以向上填充到原來的價格,然后如果它超過了原始價格,我們可以向下填充。 我們可以這樣做:

    ax1.fill_between(date, closep[0], closep)

    會生成:

    如果我們想用紅色和綠色填充來展示收益/損失,那么與原始價格相比,綠色填充用于上升(注:國外股市的顏色和國內相反),紅色填充用于下跌? 沒問題! 我們可以添加一個where參數,如下所示:

    ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)

    這里,我們填充當前價格和原始價格之間的區域,其中當前價格高于原始價格。 我們給予它綠色的前景色,因為這是一個上升,而且我們使用微小的透明度。

    我們仍然不能對多邊形數據(如填充)應用標簽,但我們可以像以前一樣實現空線條,因此我們可以:

    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)

    這向我們提供了一些填充,以及用于處理標簽的空線條,我們打算將其顯示在圖例中。這里完整的代碼是:

    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')

    現在我們的結果是:

    第十三章 邊框和水平線條

    歡迎閱讀另一個定制教程,在這里我們使用 Matplotlib 討論邊框和水平線條。 有時候你可能想做的事情是改變邊框的顏色,或者甚至完全刪除它們。

    圖形的邊框基本上是圖形的邊界,其中有刻度線等東西。為了改變邊框的顏色,你可以做一些類似這樣的事情:

    ax1.spines['left'].set_color('c')

    在這里,我們引用了我們的邊框字典,表示我們要調整左邊框,然后我們使用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')

    現在我們的日期是橙色了! 接下來,讓我們來看看我們如何繪制一條水平線。 你當然可以將你創建的一組新數據繪制成一條水平線,但你不需要這樣做。 你可以:

    ax1.axhline(closep[0], color='k', linewidth=5)

    所以在這里,我們的整個代碼是:

    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')

    結果為:

    第十四章 OHLC K 線圖

    在 Matplotlib 教程中,我們將介紹如何在 Matplotlib 中創建開,高,低,關(OHLC)的 K 線圖。 這些圖表用于以精簡形式顯示時間序列股價信息。 為了實現它,我們首先需要導入一些模塊:

    import matplotlib.ticker as mticker
    from matplotlib.finance import candlestick_ohlc

    我們引入了ticker,允許我們修改圖表底部的ticker信息。 然后我們從matplotlib.finance模塊中引入candlestick_ohlc功能。

    現在,我們需要組織我們的數據來和 matplotlib 協作。 如果你剛剛加入我們,我們得到的數據如下:

    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')})

    現在,我們需要構建一個 Python 列表,其中每個元素都是數據。 我們可以修改我們的loadtxt函數,使其不解構,但隨后我們還是希望引用特定的數據點。 我們可以解決這個問題,但是我們最后可能只擁有兩個單獨的數據集。 為此,我們執行以下操作:

    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

    有了這個,我們現在將 OHLC 數據列表存儲到我們的變量ohlc。 現在我們可以這樣繪制:

    candlestick_ohlc(ax1, ohlc)

    圖表應該是這樣:

    不幸的是,x軸上的datetime數據不是日期戳的形式。 我們可以處理它:

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

    此外,紅/黑著色依我看不是最好的選擇。 我們應該使用綠色表示上升和紅色表示下降。 為此,我們可以:

    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    最后,我們可以將x標簽設置為我們想要的數量,像這樣:

    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))

    現在,完整代碼現在是這樣:

    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')

    結果為:

    還要注意,我們從前面的教程中刪除了大部分ax1的修改。

    第十五章 樣式

    在這個 Matplotlib 教程中,我們將討論樣式。 我們用于 Matplotlib 的樣式非常相似于用于 HTML 頁面的 CSS(層疊樣式表)。 正如你在這里可以看到的,我們對圖形所做的所有修改都會疊加,而且我們目前只有一個軸域。 我們可以使用for循環,至少使代碼量降低,但我們也可以在 Matplotlib 中利用這些樣式。

    樣式頁的想法是將自定義樣式寫入文件,然后,為了使用這些更改并將其應用于圖形,所有你需要做的就是導入樣式,然后使用該特定樣式。 這樣,讓我們假設你發現自己總是改變圖形的各種元素。 你不必為每個圖表編寫 25 ~ 200 行自定義代碼,只需將其寫入一個樣式,然后加載該樣式,并以兩行應用所有這些更改即可! 讓我們開始吧。

    from matplotlib import style

    接下來,我們指定要使用的樣式。 Matplotlib 已經有了幾種樣式。

    我們可以這樣來使用樣式:

    style.use('ggplot')

    除了標題,標簽的顏色是灰色的,軸域的背景是淺灰色,我們可以立即分辨字體是不同的。 我們還注意到,網格實際上是一個白色的實線。 我們的 K 線圖保持不變,主要是因為我們在事后定制它。 在樣式中加載時,更改會生效,但如果在加載樣式后編寫新的自定義代碼,你的更改也會生效。

    因為我們試圖展示樣式模塊,但是讓我們繼續,簡單繪制幾行,并暫且注釋掉 K 線圖:

    #candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
    ax1.plot(date,closep)
    ax1.plot(date,openp)

    會生成:

    已經比默認值好多了!

    樣式的另一個例子是fivethirtyeight

    你可以這樣查看所有的可用樣式:

    print(plt.style.available)

    我這里它提供了['bmh', 'dark_background', 'ggplot', 'fivethirtyeight', 'grayscale']

    讓我們嘗試dark_background

    style.use('dark_background')

    現在,如果你想制作自己的風格呢? 首先,你需要找到樣式目錄。 為了實現它,如果你知道它在哪里,你可以前往你的 matplotlib 目錄,或者你可以找到該目錄。 如果你不知道如何找到該目錄,你可以執行以下操作:

    print(plt.__file__)

    這至少會告訴你pyplot模塊的位置。

    在 matplotlib 目錄中,你需要尋找mpl-data。 然后在那里,你需要尋找stylelib。 在 Windows 上 ,我的完整路徑是:C:\Python34\Lib\site-packages\matplotlib\mpl-data\stylelib

    那里應該顯示了所有可用的.mplstyle文件。 你可以編輯、復制或重命名它們,然后在那里修改為你想要的東西。 然后,無論你用什么來命名.mplstyle文件,都要放在style.use中。

    第十六章 實時圖表

    在這篇 Matplotlib 教程中,我們將介紹如何創建實時更新圖表,可以在數據源更新時更新其圖表。 你可能希望將此用于繪制股票實時定價數據,或者可以將傳感器連接到計算機,并且顯示傳感器實時數據。 為此,我們使用 Matplotlib 的動畫功能。

    最開始:

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    from matplotlib import style

    這里,唯一的新增導入是matplotlib.animation as animation。 這是一個模塊,允許我們在顯示之后對圖形進行動畫處理。

    接下來,我們添加一些你熟悉的代碼,如果你一直關注這個系列:

    style.use('fivethirtyeight')
    
    fig = plt.figure()
    ax1 = fig.add_subplot(1,1,1)

    現在我們編寫動畫函數:

    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)

    我們在這里做的是構建數據,然后繪制它。 注意我們這里不調用plt.show()。 我們從一個示例文件讀取數據,其內容如下:

    1,5
    2,3
    3,4
    4,7
    5,4
    6,3
    7,5
    8,7
    9,4
    10,4

    我們打開上面的文件,然后存儲每一行,用逗號分割成xsys,我們將要繪制它。 然后:

    ani = animation.FuncAnimation(fig, animate, interval=1000)
    plt.show()

    我們運行動畫,將動畫放到圖表中(fig),運行animate的動畫函數,最后我們設置了 1000 的間隔,即 1000 毫秒或 1 秒。

    運行此圖表的結果應該像往常一樣生成圖表。 然后,你應該能夠使用新的坐標更新example.txt文件。 這樣做會生成一個自動更新的圖表,如下:

    第十七章 注解和文本

    在本教程中,我們將討論如何向 Matplotlib 圖形添加文本。 我們可以通過兩種方式來實現。 一種是將文本放置在圖表上的某個位置。 另一個是專門注解圖表上的繪圖,來引起注意。

    這里的起始代碼是教程 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添加文本。 我們使用我們的數據,以坐標形式給出此文本的位置。 首先給出文本的坐標,然后給出要放置的實際文本。 接下來,我們使用fontdict參數添加一個數據字典,來使用所用的字體。 在我們的字體字典中,我們將字體更改為serif,顏色為『深紅色』,然后將字體大小更改為 15。這將全部應用于我們的圖表上的文本,如下所示:

    太棒了,接下來我們可以做的是,注解某個特定的繪圖。 我們希望這樣做來給出更多的信息。 在 eBay 的例子中,也許我們想解釋某個具體繪圖,或給出一些關于發生了什么的信息。 在股價的例子中,也許有一些發生的新聞會影響價格。 你可以注解新聞來自哪里,這將有助于解釋定價變化。

    ax1.annotate('Bad News!',(date[9],highp[9]),
                 xytext=(0.8, 0.9), textcoords='axes fraction',
                 arrowprops = dict(facecolor='grey',color='grey'))

    這里,我們用ax1.annotate來注解。 我們首先傳遞我們想要注解的文本,然后傳遞我們讓這個注解指向的坐標。 我們這樣做,是因為當我們注釋時,我們可以繪制線條和指向特定點的箭頭。 接下來,我們指定xytext的位置。 它可以是像我們用于文本放置的坐標位置,但是讓我們展示另一個例子。 它可以為軸域小數,所以我們使用 0.8 和 0.9。 這意味著文本的位置在x軸的80%和y軸的90%處。 這樣,如果我們移動圖表,文本將保持在相同位置。

    執行它,會生成:

    根據你學習這個教程的時間,所指向的點可能有所不同,這只是一個注解的例子,其中有一些合理的想法,即為什么我們需要注解一些東西。

    當圖表啟動時,請嘗試單擊平移按鈕(藍色十字),然后移動圖表。 你會看到文本保持不動,但箭頭跟隨移動并繼續指向我們想要的具體的點。 這很酷吧!

    最后一個圖表的完整代碼:

    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')

    現在,使用注解,我們可以做一些其他事情,如注解股票圖表的最后價格。 這就是我們接下來要做的。

    第十八章 注解股票圖表的最后價格

    在這個 Matplotlib 教程中,我們將展示如何跟蹤股票的最后價格的示例,通過將其注解到軸域的右側,就像許多圖表應用程序會做的那樣。

    雖然人們喜歡在他們的實時圖表中看到歷史價格,他們也想看到最新的價格。 大多數應用程序做的是,在價格的y軸高度處注釋最后價格,然后突出顯示它,并在價格變化時,在框中將其略微移動。 使用我們最近學習的注解教程,我們可以添加一個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來放置最后價格的字符串值。 我們不在這里使用它,但我們將要注解的點指定為圖上最后一個點。 接下來,我們使用xytext將我們的文本放置到特定位置。 我們將它的y坐標指定為最后一個點的y坐標,x坐標指定為最后一個點的x坐標,再加上幾個點。我們這樣做是為了將它移出圖表。 將文本放在圖形外面就足夠了,但現在它只是一些浮動文本。

    我們使用bbox參數在文本周圍創建一個框。 我們使用bbox_props創建一個屬性字典,包含盒子樣式,然后是白色(w)前景色,黑色(k)邊框顏色并且線寬為 1。 更多框樣式請參閱 matplotlib 注解文檔

    最后,這個注解向右移動,需要我們使用subplots_adjust來創建一些新空間:

    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')

    結果為:

    第十九章 子圖

    在這個 Matplotlib 教程中,我們將討論子圖。 有兩種處理子圖的主要方法,用于在同一圖上創建多個圖表。 現在,我們將從一個干凈的代碼開始。 如果你一直關注這個教程,那么請確保保留舊的代碼,或者你可以隨時重新查看上一個教程的代碼。

    首先,讓我們使用樣式,創建我們的圖表,然后創建一個隨機創建示例繪圖的函數:

    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

    現在,我們開始使用add_subplot方法創建子圖:

    ax1 = fig.add_subplot(221)
    ax2 = fig.add_subplot(222)
    ax3 = fig.add_subplot(212)

    它的工作原理是使用 3 個數字,即:行數(numRows)、列數(numCols)和繪圖編號(plotNum)。

    所以,221 表示兩行兩列的第一個位置。222 是兩行兩列的第二個位置。最后,212 是兩行一列的第二個位置。

    2x2:
    
    +-----+-----+
    |  1  |  2  |
    +-----+-----+
    |  3  |  4  |
    +-----+-----+
    
    2x1:
    
    +-----------+
    |     1     |
    +-----------+
    |     2     |
    +-----------+

    譯者注:原文此處表述有誤,譯文已更改。

    譯者注:221是縮寫形式,僅在行數乘列數小于 10 時有效,否則要寫成2,2,1

    此代碼結果為:

    這就是add_subplot。 嘗試一些你認為可能很有趣的配置,然后嘗試使用add_subplot創建它們,直到你感到滿意。

    接下來,讓我們介紹另一種方法,它是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不能讓我們使一個繪圖覆蓋多個位置。 但是這個新的subplot2grid可以。 所以,subplot2grid的工作方式是首先傳遞一個元組,它是網格形狀。 我們傳遞了(6,1),這意味著整個圖表分為六行一列。 下一個元組是左上角的起始點。 對于ax1,這是0,0,因此它起始于頂部。 接下來,我們可以選擇指定rowspancolspan。 這是軸域所占的行數和列數。

    6x1:
    
              colspan=1
    (0,0)   +-----------+
            |    ax1    | rowspan=1
    (1,0)   +-----------+
            |           |
            |    ax2    | rowspan=4
            |           |
            |           |
    (5,0)   +-----------+
            |    ax3    | rowspan=1
            +-----------+

    結果為:

    顯然,我們在這里有一些重疊的問題,我們可以調整子圖來處理它。

    再次,嘗試構思各種配置的子圖,使用subplot2grid制作出來,直到你感到滿意!

    我們將繼續使用subplot2grid,將它應用到我們已經逐步建立的代碼中,我們將在下一個教程中繼續。

    第二十章 將子圖應用于我們的圖表

    在這個 Matplotlib 教程中,我們將處理我們以前教程的代碼,并實現上一個教程中的子圖配置。 我們的起始代碼是這樣:

    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')

    一個主要的改動是修改軸域的定義:

    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)

    現在,ax2是我們實際上在繪制的股票價格數據。 頂部和底部圖表將作為指標信息。

    在我們繪制數據的代碼中,我們需要將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')

    結果為:

    第二十一章 更多指標數據

    在這篇 Matplotlib 教程中,我們介紹了添加一些簡單的函數來計算數據,以便我們填充我們的軸域。 一個是簡單的移動均值,另一個是簡單的價格 HML 計算。

    這些新函數是:

    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

    你不需要太過專注于理解移動均值的工作原理,我們只是對樣本數據來計算它,以便可以學習更多自定義 Matplotlib 的東西。

    我們還想在腳本頂部為移動均值定義一些值:

    MA1 = 10
    MA2 = 30

    下面,在我們的graph_data函數中:

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])
    
    h_l = list(map(high_minus_low, highp, lowp))

    在這里,我們計算兩個移動均值和 HML。

    我們還定義了一個『起始』點。 我們這樣做是因為我們希望我們的數據排成一行。 例如,20 天的移動均值需要 20 個數據點。 這意味著我們不能在第 5 天真正計算 20 天的移動均值。 因此,當我們計算移動均值時,我們會失去一些數據。 為了處理這種數據的減法,我們使用起始變量來計算應該有多少數據。 這里,我們可以安全地使用[-start:]繪制移動均值,并且如果我們希望的話,對所有繪圖進行上述步驟來排列數據。

    接下來,我們可以在ax1上繪制 HML,通過這樣:

    ax1.plot_date(date,h_l,'-')

    最后我們可以通過這樣向ax3添加移動均值:

    ax3.plot(date[-start:], ma1[-start:])
    ax3.plot(date[-start:], ma2[-start:])

    我們的完整代碼,包括增加我們所用的時間范圍:

    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')

    代碼效果如圖:

    第二十二章 自定義填充、修剪和清除

    歡迎閱讀另一個 Matplotlib 教程! 在本教程中,我們將清除圖表,然后再做一些自定義。

    我們當前的代碼是:

    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')

    現在我認為向我們的移動均值添加自定義填充是一個很好的主意。 移動均值通常用于說明價格趨勢。 這個想法是,你可以計算一個快速和一個慢速的移動均值。 一般來說,移動均值用于使價格變得『平滑』。 他們總是『滯后』于價格,但是我們的想法是計算不同的速度。 移動均值越大就越『慢』。 所以這個想法是,如果『較快』的移動均值超過『較慢』的均值,那么價格就會上升,這是一件好事。 如果較快的 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)

    下面,我們會碰到一些我們可解決的問題:

    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刻度標簽設置為false,去掉它們!

    我們還可以通過在軸域定義中執行以下操作,為每個軸域提供自定義標簽:

    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刻度有許多數字,經常互相覆蓋。 我們也看到軸之間互相重疊。 我們可以這樣:

    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='lower'))

    所以,這里發生的是,我們通過首先將nbins設置為 5 來修改我們的y軸對象。這意味著我們顯示的標簽最多為 5 個。然后我們還可以『修剪』標簽,因此,在我們這里, 我們修剪底部標簽,這會使它消失,所以現在不會有任何文本重疊。 我們仍然可能打算修剪ax2的頂部標簽,但這里是我們目前為止的源代碼:

    當前的源碼:

    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 軸

    在這個 Matplotlib 數據可視化教程中,我們將討論sharex選項,它允許我們在圖表之間共享x軸。將sharex看做『復制 x』也許更好。

    在我們開始之前,首先我們要做些修剪并在另一個軸上設置最大刻度數,如下所示:

    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))

    以及

    ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

    現在,讓我們共享所有軸域之間的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')

    上面,對于ax2ax3,我們添加一個新的參數,稱為sharex,然后我們說,我們要與ax1共享x軸。

    使用這種方式,我們可以加載圖表,然后我們可以放大到一個特定的點,結果將是這樣:

    所以這意味著所有軸域沿著它們的x軸一起移動。 這很酷吧!

    接下來,讓我們將[-start:]應用到所有數據,所以所有軸域都起始于相同地方。 我們最終的代碼為:

    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')

    下面我們會討論如何創建多個y軸。

    第二十四章 多個 Y 軸

    在這篇 Matplotlib 教程中,我們將介紹如何在同一子圖上使用多個 Y 軸。 在我們的例子中,我們有興趣在同一個圖表及同一個子圖上繪制股票價格和交易量。

    為此,首先我們需要定義一個新的軸域,但是這個軸域是ax2僅帶有x軸的『雙生子』。

    這足以創建軸域了。我們叫它ax2v,因為這個軸域是ax2加交易量。

    現在,我們在軸域上定義繪圖,我們將添加:

    ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)

    我們在 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__)
    
    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')

    會生成:

    太棒了,到目前為止還不錯。 接下來,我們可能要刪除新y軸上的標簽,然后我們也可能不想讓交易量占用太多空間。 沒問題:

    首先:

    ax2v.axes.yaxis.set_ticklabels([])

    上面將y刻度標簽設置為一個空列表,所以不會有任何標簽了。

    譯者注:所以將標簽刪除之后,添加新軸的意義是什么?直接在原軸域上繪圖就可以了。

    接下來,我們可能要將網格設置為false,使軸域上不會有雙網格:

    ax2v.grid(False)

    最后,為了處理交易量占用很多空間,我們可以做以下操作:

    ax2v.set_ylim(0, 3*volume.max())

    所以這設置y軸顯示范圍從 0 到交易量的最大值的 3 倍。 這意味著,在最高點,交易量最多可占據圖形的33%。 所以,增加volume.max的倍數越多,空間就越小/越少。

    現在,我們的圖表為:

    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')

    到這里,我們差不多完成了。 這里唯一的缺陷是一個好的圖例。 一些線條是顯而易見的,但人們可能會好奇移動均值的參數是什么,我們這里是 10 和 30。 添加自定義圖例是下一個教程中涉及的內容。

    第二十五章 自定義圖例

    在這篇 Matplotlib 教程中,我們將討論自定義圖例。 我們已經介紹了添加圖例的基礎知識

    圖例的主要問題通常是圖例阻礙了數據的展示。 這里有幾個選項。 一個選項是將圖例放在軸域外,但是我們在這里有多個子圖,這是非常困難的。 相反,我們將使圖例稍微小一點,然后應用一個透明度。

    首先,為了創建一個圖例,我們需要向我們的數據添加我們想要顯示在圖例上的標簽。

    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'))

    請注意,我們通過創建空行為交易量添加了標簽。 請記住,我們不能對任何填充應用標簽,所以這就是我們添加這個空行的原因。

    現在,我們可以在右下角添加圖例,通過在plt.show()之前執行以下操作:

    ax1.legend()
    ax2v.legend()
    ax3.legend()

    會生成:

    所以,我們可以看到,圖例還是占用了一些位置。 讓我們更改位置,大小并添加透明度:

    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(上中間)。 有很多地方可放置圖例,我們可以為參數傳入不同的位置號碼,來看看它們都位于哪里。 ncol參數允許我們指定圖例中的列數。 這里只有一列,如果圖例中有 2 個項目,他們將堆疊在一列中。 最后,我們將尺寸規定為更小。 之后,我們對整個圖例應用0.4的透明度。

    現在我們的結果為:

    完整的代碼為:

    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')

    現在我們可以看到圖例,但也看到了圖例下的任何信息。 還要注意額外函數fig.savefig。 這是自動保存圖形的圖像的方式。 我們還可以設置所保存的圖形的前景色,使背景不是白色的,如我們的例子所示。

    這就是目前為止,我想要顯示的典型 Matplotlib 圖表。 接下來,我們將涉及Basemap,它是一個 Matplotlib 擴展,用于繪制地理位置,然后我打算講解 Matplotlib 中的 3D 圖形。

    第二十六章 Basemap 地理繪圖

    在這個 Matplotlib 教程中,我們將涉及地理繪圖模塊BasemapBasemap是 Matplotlib 的擴展。

    為了使用Basemap,我們首先需要安裝它。 為了獲得Basemap,你可以從這里獲取:http://matplotlib.org/basemap/users/download.html,或者你可以訪問http://www.lfd.uci.edu/~gohlke/pythonlibs/

    如果你在安裝Basemap時遇到問題,請查看pip安裝教程

    一旦你安裝了Basemap,你就可以創建地圖了。 首先,讓我們投影一個簡單的地圖。 為此,我們需要導入Basemappyplot,創建投影,至少繪制某種輪廓或數據,然后我們可以顯示圖形。

    from mpl_toolkits.basemap import Basemap
    import matplotlib.pyplot as plt
    
    m = Basemap(projection='mill')
    m.drawcoastlines()
    plt.show()

    上面的代碼結果如下:

    這是使用 Miller 投影完成的,這只是許多Basemap投影選項之一。

    第二十七章 Basemap 自定義

    在這篇 Matplotlib 教程中,我們繼續使用Basemap地理繪圖擴展。 我們將展示一些我們可用的自定義選項。

    首先,從上一個教程中獲取我們的起始代碼:

    from mpl_toolkits.basemap import Basemap
    import matplotlib.pyplot as plt
    
    m = Basemap(projection='mill')
    m.drawcoastlines()
    plt.show()

    我們可以從放大到特定區域來開始:

    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()

    這里的參數是:

    • llcrnrlat - 左下角的緯度
    • llcrnrlon - 左下角的經度
    • urcrnrlat - 右上角的緯度
    • urcrnrlon - 右上角的經度

    此外,坐標需要轉換,其中西經和南緯坐標是負值,北緯和東經坐標是正值。

    使用這些坐標,Basemap會選擇它們之間的區域。

    下面,我們要使用一些東西,類似:

    m.drawcountries(linewidth=2)

    這會畫出國家,并使用線寬為 2 的線條生成分界線。

    另一個選項是:

    m.drawstates(color='b')

    這會用藍色線條畫出州。

    你也可以執行:

    m.drawcounties(color='darkred')

    這會畫出國家。

    所以,我們的代碼是:

    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()

    很難說,但我們定義了美國的區縣的線條。 我們可以使用放大鏡放大Basemap圖形,就像其他圖形那樣,會生成:

    另一個有用的選項是Basemap調用中的『分辨率』選項。

    m = Basemap(projection='mill',
                llcrnrlat = -90,
                llcrnrlon = -180,
                urcrnrlat = 90,
                urcrnrlon = 180,
                resolution='l')

    分辨率的選項為:

    • c - 粗糙
    • l - 低
    • h - 高
    • f - 完整

    對于更高的分辨率,你應該放大到很大,否則這可能只是浪費。

    另一個選項是使用etopo()繪制地形,如:

    m.etopo()

    使用drawcountries方法繪制此圖形會生成:

    最后,有一個藍色的大理石版本,你可以調用:

    m.bluemarble()

    會生成:

    目前為止的代碼:

    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()
    ````
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    
    # 第二十八章 在 Basemap 中繪制坐標
    
    歡迎閱讀另一個 Matplotlib Basemap 教程。 在本教程中,我們將介紹如何繪制單個坐標,以及如何在地理區域中連接這些坐標。
    
    首先,我們將從一些基本的起始數據開始:
    
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    
    ```py
    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')

    接下來,我們可以繪制坐標,從獲得它們的實際坐標開始。 記住,南緯和西經坐標需要轉換為負值。 例如,紐約市是北緯40.7127西經74.0059。 我們可以在我們的程序中定義這些坐標,如:

    NYClat, NYClon = 40.7127, -74.0059

    之后我們將這些轉換為要繪制的xy坐標。

    xpt, ypt = m(NYClon, NYClat)

    注意這里,我們現在已經將坐標順序翻轉為lon, lat(緯度,經度)。 坐標通常以lat, lon順序給出。 然而,在圖形中,lat, long轉換為y, x,我們顯然不需要。 在某些時候,你必須翻轉它們。 不要忘記這部分!

    最后,我們可以繪制如下的坐標:

    m.plot(xpt, ypt, 'c*', markersize=15)

    這個圖表上有一個青色的星,大小為 15。更多標記類型請參閱:Matplotlib 標記文檔

    接下來,讓我們再畫一個位置,洛杉磯,加利福尼亞:

    LAlat, LAlon = 34.05, -118.25
    xpt, ypt = m(LAlon, LAlat)
    m.plot(xpt, ypt, 'g^', markersize=15)

    這次我們畫出一個綠色三角,執行代碼會生成:

    如果我們想連接這些圖塊怎么辦?原來,我們可以像其它 Matplotlib 圖表那樣實現它。

    首先,我們將那些xptypt坐標保存到列表,類似這樣的東西:

    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')

    我們的完整代碼為:

    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()

    結果為:

    這就是Basemap的全部了,下一章關于 Matplotlib 的 3D 繪圖。

    第二十九章 3D 繪圖

    您好,歡迎閱讀 Matplotlib 教程中的 3D 繪圖。 Matplotlib 已經內置了三維圖形,所以我們不需要再下載任何東西。 首先,我們需要引入一些完整的模塊:

    from mpl_toolkits.mplot3d import axes3d
    import matplotlib.pyplot as plt

    使用axes3d是因為它需要不同種類的軸域,以便在三維中實際繪制一些東西。 下面:

    fig = plt.figure()
    ax1 = fig.add_subplot(111, projection='3d')

    在這里,我們像通常一樣定義圖形,然后我們將ax1定義為通常的子圖,只是這次使用 3D 投影。 我們需要這樣做,以便提醒 Matplotlib 我們要提供三維數據。

    現在讓我們創建一些 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()

    我們完整的代碼是:

    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()

    結果為(包括所用的樣式):

    這些 3D 圖形可以進行交互。 首先,您可以使用鼠標左鍵單擊并拖動來移動圖形。 您還可以使用鼠標右鍵單擊并拖動來放大或縮小。

    第三十章 3D 散點圖

    歡迎閱讀另一個 3D Matplotlib 教程,會涉及如何繪制三維散點圖。

    繪制 3D 散點圖非常類似于通常的散點圖以及 3D 線框圖。

    一個簡單示例:

    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()

    結果為:

    要記住你可以修改這些繪圖的大小和標記,就像通常的散點圖那樣。

    第三十一章 3D 條形圖

    在這個 Matplotlib 教程中,我們要介紹 3D 條形圖。 3D 條形圖是非常獨特的,因為它允許我們繪制多于 3 個維度。 不,你不能超過第三個維度來繪制,但你可以繪制多于 3 個維度。

    對于條形圖,你需要擁有條形的起點,條形的高度和寬度。 但對于 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')
    
    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()

    注意這里,我們必須定義xyz,然后是 3 個維度的寬度、高度和深度。 這會生成:

    第三十二章 總結

    歡迎閱讀最后的 Matplotlib 教程。 在這里我們將整理整個系列,并顯示一個稍微更復雜的 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()

    如果你從一開始就關注這個教程的話,那么你已經學會了 Matplotlib 提供的大部分內容。 你可能不相信,但Matplotlib 仍然可以做很多其他的事情! 請繼續學習,你可以隨時訪問 Matplotlib.org,并查看示例和圖庫頁面。

    如果你發現自己大量使用 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()

    版權聲明:本文為weixin_34064653原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_34064653/article/details/89723510

    智能推薦

    python數據科學包---matplotlib(3)

    注釋 主要用到的是plt.annotate() xy : (float, float) The point (x,y) to annotate. xytext : (float, float), optional The position (x,y) to place the text at. If None, defaults to xy. arrowprops : dict, optional...

    用 Python 入門數據科學

      使用 Python 開展數據科學為你提供了無限的潛力,使你能夠以有意義和啟發性的方式解析、解釋和組織數據。 數據科學是計算領域一個令人興奮的新領域,它圍繞分析、可視化和關聯以解釋我們的計算機收集的有關世界的無限信息而建立。當然,稱其為“新”領域有點不誠實,因為該學科是統計學、數據分析和普通而古老的科學觀察派生而來的。 但是數據科學是這些學科的形式化分支,擁有自...

    Python極簡教程_Python爬取網站數據_非常詳細的入門教程

    簡述:我們都知道,現在市面上Python這門編程語言很火,Python 是一個高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言,也就說說類似于PHP這樣的弱類型語言,但是功能很強大,常用的功能體現在爬取網頁數據,實現思路就是通過網頁鏈接URL得到網頁的源代碼,根據源代碼以及相關正則表達式規則篩選出需要的信息,打到爬取有效信息的目標。 開發環境準備:開發環境用的idea,依賴庫分別是requ...

    Python小白數據科學教程:Pandas (上)

    點擊“簡說Python”,選擇“置頂/星標公眾號” 福利干貨,第一時間送達! 本文轉載自公眾號 | 王的機器 作者 | 王圣元 本文偏長(2w+字),老表建議先收藏,然后轉發朋友圈,然后吃飯、休閑時慢慢看,基礎知識重在反復看,反復記,反復練。 【注:本帖小節 2.2 用萬礦里的 WindPy 來下載金融數據】 0 引言 Panda...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡