<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 第 9 章 繪圖和可視化 信息可視化(也叫繪圖)是數據分析中最重要的工作之一。它可能是探索過程的一部分,例如,幫助我們找出異常值、必要的數據轉換、得出有關模型的idea等。另外,做一個可交互的數據可視化也許是工作的最終目標。Python有許多庫進行靜態或動態的數據可視化,但我這里重要關注于matplotlib(http://matplotlib.org/)和基于它的庫。 matplotlib是一個用于創建出版質量圖表的桌面繪圖包(主要是2D方面)。該項目是由John Hunter于2002年啟動的,其目的是為Python構建一個MATLAB式的繪圖接口。matplotlib和IPython社區進行合作,簡化了從IPython shell(包括現在的Jupyter notebook)進行交互式繪圖。matplotlib支持各種操作系統上許多不同的GUI后端,而且還能將圖片導出為各種常見的矢量(vector)和光柵(raster)圖:PDF、SVG、JPG、PNG、BMP、GIF等。除了幾張,本書中的大部分圖都是用它生成的。 隨著時間的發展,matplotlib衍生出了多個數據可視化的工具集,它們使用matplotlib作為底層。其中之一是seaborn(http://seaborn.pydata.org/),本章后面會學習它。 學習本章代碼案例的最簡單方法是在Jupyter notebook進行交互式繪圖。在Jupyter notebook中執行下面的語句: ```python %matplotlib notebook ``` # 9.1 matplotlib API入門 matplotlib的通常引入約定是: ```python In [11]: import matplotlib.pyplot as plt ``` 在Jupyter中運行%matplotlib notebook(或在IPython中運行%matplotlib),就可以創建一個簡單的圖形。如果一切設置正確,會看到圖9-1: ```python In [12]: import numpy as np In [13]: data = np.arange(10) In [14]: data Out[14]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [15]: plt.plot(data) ``` ![圖9-1 簡單的線圖](https://img.kancloud.cn/d0/72/d072b332fe8a2c5c73421f4892260ba6_1223x761.png) 雖然seaborn這樣的庫和pandas的內置繪圖函數能夠處理許多普通的繪圖任務,但如果需要自定義一些高級功能的話就必須學習matplotlib API。 >筆記:雖然本書沒有詳細地討論matplotlib的各種功能,但足以將你引入門。matplotlib的示例庫和文檔是學習高級特性的最好資源。 ## Figure和Subplot matplotlib的圖像都位于Figure對象中。你可以用plt.figure創建一個新的Figure: ```python In [16]: fig = plt.figure() ``` 如果用的是IPython,這時會彈出一個空窗口,但在Jupyter中,必須再輸入更多命令才能看到。plt.figure有一些選項,特別是figsize,它用于確保當圖片保存到磁盤時具有一定的大小和縱橫比。 不能通過空Figure繪圖。必須用add_subplot創建一個或多個subplot才行: ```python In [17]: ax1 = fig.add_subplot(2, 2, 1) ``` 這條代碼的意思是:圖像應該是2×2的(即最多4張圖),且當前選中的是4個subplot中的第一個(編號從1開始)。如果再把后面兩個subplot也創建出來,最終得到的圖像如圖9-2所示: ```python In [18]: ax2 = fig.add_subplot(2, 2, 2) In [19]: ax3 = fig.add_subplot(2, 2, 3) ``` ![圖9-2 帶有三個subplot的Figure](https://img.kancloud.cn/44/e8/44e84114493a9edfaaa154d31b2b3431_1240x755.png) >提示:使用Jupyter notebook有一點不同,即每個小窗重新執行后,圖形會被重置。因此,對于復雜的圖形,,你必須將所有的繪圖命令存在一個小窗里。 這里,我們運行同一個小窗里的所有命令: ```python fig = plt.figure() ax1 = fig.add_subplot(2, 2, 1) ax2 = fig.add_subplot(2, 2, 2) ax3 = fig.add_subplot(2, 2, 3) ``` 如果這時執行一條繪圖命令(如plt.plot([1.5, 3.5, -2, 1.6])),matplotlib就會在最后一個用過的subplot(如果沒有則創建一個)上進行繪制,隱藏創建figure和subplot的過程。因此,如果我們執行下列命令,你就會得到如圖9-3所示的結果: ```python In [20]: plt.plot(np.random.randn(50).cumsum(), 'k--') ``` ![圖9-3 繪制一次之后的圖像](https://img.kancloud.cn/59/8c/598c1949cf4e67d68e7fb965caff184b_1240x745.png) "k--"是一個線型選項,用于告訴matplotlib繪制黑色虛線圖。上面那些由fig.add_subplot所返回的對象是AxesSubplot對象,直接調用它們的實例方法就可以在其它空著的格子里面畫圖了,如圖9-4所示: ```python In [21]: ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3) In [22]: ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30)) ``` ![圖9-4 繼續繪制兩次之后的圖像](https://img.kancloud.cn/3c/ec/3cecd2e57d7807d9e238f28d24c70978_1240x747.png) 你可以在matplotlib的文檔中找到各種圖表類型。 創建包含subplot網格的figure是一個非常常見的任務,matplotlib有一個更為方便的方法plt.subplots,它可以創建一個新的Figure,并返回一個含有已創建的subplot對象的NumPy數組: ```python In [24]: fig, axes = plt.subplots(2, 3) In [25]: axes Out[25]: array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fb626374048>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fb62625db00>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fb6262f6c88>], [<matplotlib.axes._subplots.AxesSubplot object at 0x7fb6261a36a0>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fb626181860>, <matplotlib.axes._subplots.AxesSubplot object at 0x7fb6260fd4e0>]], dtype =object) ``` 這是非常實用的,因為可以輕松地對axes數組進行索引,就好像是一個二維數組一樣,例如axes[0,1]。你還可以通過sharex和sharey指定subplot應該具有相同的X軸或Y軸。在比較相同范圍的數據時,這也是非常實用的,否則,matplotlib會自動縮放各圖表的界限。有關該方法的更多信息,請參見表9-1。 ![表9-1 pyplot.subplots的選項](https://img.kancloud.cn/fe/f5/fef5e0459c71880ae155477d330b581e_554x179.png) ## 調整subplot周圍的間距 默認情況下,matplotlib會在subplot外圍留下一定的邊距,并在subplot之間留下一定的間距。間距跟圖像的高度和寬度有關,因此,如果你調整了圖像大小(不管是編程還是手工),間距也會自動調整。利用Figure的subplots_adjust方法可以輕而易舉地修改間距,此外,它也是個頂級函數: ```python subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None) ``` wspace和hspace用于控制寬度和高度的百分比,可以用作subplot之間的間距。下面是一個簡單的例子,其中我將間距收縮到了0(如圖9-5所示): ```python fig, axes = plt.subplots(2, 2, sharex=True, sharey=True) for i in range(2): for j in range(2): axes[i, j].hist(np.random.randn(500), bins=50, color='k', alpha=0.5) plt.subplots_adjust(wspace=0, hspace=0) ``` ![圖9-5 各subplot之間沒有間距](https://img.kancloud.cn/b1/3c/b13c07943890d6efcab61273a20fab0b_1237x761.png) 不難看出,其中的軸標簽重疊了。matplotlib不會檢查標簽是否重疊,所以對于這種情況,你只能自己設定刻度位置和刻度標簽。后面幾節將會詳細介紹該內容。 ## 顏色、標記和線型 matplotlib的plot函數接受一組X和Y坐標,還可以接受一個表示顏色和線型的字符串縮寫。例如,要根據x和y繪制綠色虛線,你可以執行如下代碼: ```python ax.plot(x, y, 'g--') ``` 這種在一個字符串中指定顏色和線型的方式非常方便。在實際中,如果你是用代碼繪圖,你可能不想通過處理字符串來獲得想要的格式。通過下面這種更為明確的方式也能得到同樣的效果: ```python ax.plot(x, y, linestyle='--', color='g') ``` 常用的顏色可以使用顏色縮寫,你也可以指定顏色碼(例如,'#CECECE')。你可以通過查看plot的文檔字符串查看所有線型的合集(在IPython和Jupyter中使用plot?)。 線圖可以使用標記強調數據點。因為matplotlib可以創建連續線圖,在點之間進行插值,因此有時可能不太容易看出真實數據點的位置。標記也可以放到格式字符串中,但標記類型和線型必須放在顏色后面(見圖9-6): ```python In [30]: from numpy.random import randn In [31]: plt.plot(randn(30).cumsum(), 'ko--') ``` ![圖9-6 帶有標記的線型圖示例](https://img.kancloud.cn/8f/30/8f30d9f49190d46f0e08444124f244f7_1240x748.png) 還可以將其寫成更為明確的形式: ```python plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o') ``` 在線型圖中,非實際數據點默認是按線性方式插值的。可以通過drawstyle選項修改(見圖9-7): ```python In [33]: data = np.random.randn(30).cumsum() In [34]: plt.plot(data, 'k--', label='Default') Out[34]: [<matplotlib.lines.Line2D at 0x7fb624d86160>] In [35]: plt.plot(data, 'k-', drawstyle='steps-post', label='steps-post') Out[35]: [<matplotlib.lines.Line2D at 0x7fb624d869e8>] In [36]: plt.legend(loc='best') ``` ![圖9-7 不同drawstyle選項的線型圖](https://img.kancloud.cn/b7/53/b7538853ad3b1458e4015791c0e36029_1223x761.png) 你可能注意到運行上面代碼時有輸出<matplotlib.lines.Line2D at ...>。matplotlib會返回引用了新添加的子組件的對象。大多數時候,你可以放心地忽略這些輸出。這里,因為我們傳遞了label參數到plot,我們可以創建一個plot圖例,指明每條使用plt.legend的線。 >筆記:你必須調用plt.legend(或使用ax.legend,如果引用了軸的話)來創建圖例,無論你繪圖時是否傳遞label標簽選項。 ## 刻度、標簽和圖例 對于大多數的圖表裝飾項,其主要實現方式有二:使用過程型的pyplot接口(例如,matplotlib.pyplot)以及更為面向對象的原生matplotlib API。 pyplot接口的設計目的就是交互式使用,含有諸如xlim、xticks和xticklabels之類的方法。它們分別控制圖表的范圍、刻度位置、刻度標簽等。其使用方式有以下兩種: - 調用時不帶參數,則返回當前的參數值(例如,plt.xlim()返回當前的X軸繪圖范圍)。 - 調用時帶參數,則設置參數值(例如,plt.xlim([0,10])會將X軸的范圍設置為0到10)。 所有這些方法都是對當前或最近創建的AxesSubplot起作用的。它們各自對應subplot對象上的兩個方法,以xlim為例,就是ax.get_xlim和ax.set_xlim。我更喜歡使用subplot的實例方法(因為我喜歡明確的事情,而且在處理多個subplot時這樣也更清楚一些)。當然你完全可以選擇自己覺得方便的那個。 ## 設置標題、軸標簽、刻度以及刻度標簽 為了說明自定義軸,我將創建一個簡單的圖像并繪制一段隨機漫步(如圖9-8所示): ```python In [37]: fig = plt.figure() In [38]: ax = fig.add_subplot(1, 1, 1) In [39]: ax.plot(np.random.randn(1000).cumsum()) ``` ![圖9-8 用于演示xticks的簡單線型圖(帶有標簽)](https://img.kancloud.cn/89/61/8961f01eb554ea6c9d1612d3794b79ff_1240x753.png) 要改變x軸刻度,最簡單的辦法是使用set_xticks和set_xticklabels。前者告訴matplotlib要將刻度放在數據范圍中的哪些位置,默認情況下,這些位置也就是刻度標簽。但我們可以通過set_xticklabels將任何其他的值用作標簽: ```python In [40]: ticks = ax.set_xticks([0, 250, 500, 750, 1000]) In [41]: labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], ....: rotation=30, fontsize='small') ``` rotation選項設定x刻度標簽傾斜30度。最后,再用set_xlabel為X軸設置一個名稱,并用set_title設置一個標題(見圖9-9的結果): ```python In [42]: ax.set_title('My first matplotlib plot') Out[42]: <matplotlib.text.Text at 0x7fb624d055f8> In [43]: ax.set_xlabel('Stages') ``` ![圖9-9 用于演示xticks的簡單線型圖](https://img.kancloud.cn/86/32/8632462101fd01959b0b1cb0d00c77e1_1240x827.png) Y軸的修改方式與此類似,只需將上述代碼中的x替換為y即可。軸的類有集合方法,可以批量設定繪圖選項。前面的例子,也可以寫為: ```python props = { 'title': 'My first matplotlib plot', 'xlabel': 'Stages' } ax.set(**props) ``` ## 添加圖例 圖例(legend)是另一種用于標識圖表元素的重要工具。添加圖例的方式有多種。最簡單的是在添加subplot的時候傳入label參數: ```python In [44]: from numpy.random import randn In [45]: fig = plt.figure(); ax = fig.add_subplot(1, 1, 1) In [46]: ax.plot(randn(1000).cumsum(), 'k', label='one') Out[46]: [<matplotlib.lines.Line2D at 0x7fb624bdf860>] In [47]: ax.plot(randn(1000).cumsum(), 'k--', label='two') Out[47]: [<matplotlib.lines.Line2D at 0x7fb624be90f0>] In [48]: ax.plot(randn(1000).cumsum(), 'k.', label='three') Out[48]: [<matplotlib.lines.Line2D at 0x7fb624be9160>] ``` 在此之后,你可以調用ax.legend()或plt.legend()來自動創建圖例(結果見圖9-10): ```python In [49]: ax.legend(loc='best') ``` ![圖9-10 帶有三條線以及圖例的簡單線型圖](https://img.kancloud.cn/01/6d/016d999d3f1e23284ea2c54149896032_1240x753.png) legend方法有幾個其它的loc位置參數選項。請查看文檔字符串(使用ax.legend?)。 loc告訴matplotlib要將圖例放在哪。如果你不是吹毛求疵的話,"best"是不錯的選擇,因為它會選擇最不礙事的位置。要從圖例中去除一個或多個元素,不傳入label或傳入label='_nolegend_'即可。(中文第一版這里把best錯寫成了beat) ## 注解以及在Subplot上繪圖 除標準的繪圖類型,你可能還希望繪制一些子集的注解,可能是文本、箭頭或其他圖形等。注解和文字可以通過text、arrow和annotate函數進行添加。text可以將文本繪制在圖表的指定坐標(x,y),還可以加上一些自定義格式: ```python ax.text(x, y, 'Hello world!', family='monospace', fontsize=10) ``` 注解中可以既含有文本也含有箭頭。例如,我們根據最近的標準普爾500指數價格(來自Yahoo!Finance)繪制一張曲線圖,并標出2008年到2009年金融危機期間的一些重要日期。你可以在Jupyter notebook的一個小窗中試驗這段代碼(圖9-11是結果): ```python from datetime import datetime fig = plt.figure() ax = fig.add_subplot(1, 1, 1) data = pd.read_csv('examples/spx.csv', index_col=0, parse_dates=True) spx = data['SPX'] spx.plot(ax=ax, style='k-') crisis_data = [ (datetime(2007, 10, 11), 'Peak of bull market'), (datetime(2008, 3, 12), 'Bear Stearns Fails'), (datetime(2008, 9, 15), 'Lehman Bankruptcy') ] for date, label in crisis_data: ax.annotate(label, xy=(date, spx.asof(date) + 75), xytext=(date, spx.asof(date) + 225), arrowprops=dict(facecolor='black', headwidth=4, width=2, headlength=4), horizontalalignment='left', verticalalignment='top') # Zoom in on 2007-2010 ax.set_xlim(['1/1/2007', '1/1/2011']) ax.set_ylim([600, 1800]) ax.set_title('Important dates in the 2008-2009 financial crisis') ``` ![圖9-11 2008-2009年金融危機期間的重要日期](https://img.kancloud.cn/51/39/5139ca9689707fd1b3b9f8d93665381b_1240x724.png) 這張圖中有幾個重要的點要強調:ax.annotate方法可以在指定的x和y坐標軸繪制標簽。我們使用set_xlim和set_ylim人工設定起始和結束邊界,而不使用matplotlib的默認方法。最后,用ax.set_title添加圖標標題。 更多有關注解的示例,請訪問matplotlib的在線示例庫。 圖形的繪制要麻煩一些。matplotlib有一些表示常見圖形的對象。這些對象被稱為塊(patch)。其中有些(如Rectangle和Circle),可以在matplotlib.pyplot中找到,但完整集合位于matplotlib.patches。 要在圖表中添加一個圖形,你需要創建一個塊對象shp,然后通過ax.add_patch(shp)將其添加到subplot中(如圖9-12所示): ```python fig = plt.figure() ax = fig.add_subplot(1, 1, 1) rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3) circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3) pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]], color='g', alpha=0.5) ax.add_patch(rect) ax.add_patch(circ) ax.add_patch(pgon) ``` ![圖9-12 由三個塊圖形組成的圖](https://img.kancloud.cn/96/86/9686ed1345e00c2d63ee11919ccc63dc_1240x637.png) 如果查看許多常見圖表對象的具體實現代碼,你就會發現它們其實就是由塊patch組裝而成的。 ## 將圖表保存到文件 利用plt.savefig可以將當前圖表保存到文件。該方法相當于Figure對象的實例方法savefig。例如,要將圖表保存為SVG文件,你只需輸入: ```python plt.savefig('figpath.svg') ``` 文件類型是通過文件擴展名推斷出來的。因此,如果你使用的是.pdf,就會得到一個PDF文件。我在發布圖片時最常用到兩個重要的選項是dpi(控制“每英寸點數”分辨率)和bbox_inches(可以剪除當前圖表周圍的空白部分)。要得到一張帶有最小白邊且分辨率為400DPI的PNG圖片,你可以: ```python plt.savefig('figpath.png', dpi=400, bbox_inches='tight') ``` savefig并非一定要寫入磁盤,也可以寫入任何文件型的對象,比如BytesIO: ```python from io import BytesIO buffer = BytesIO() plt.savefig(buffer) plot_data = buffer.getvalue() ``` 表9-2列出了savefig的其它選項。 ![表9-2 Figure.savefig的選項](https://img.kancloud.cn/1f/c5/1fc5f726e159e33cdf806992f1e371bd_554x218.png) ## matplotlib配置 matplotlib自帶一些配色方案,以及為生成出版質量的圖片而設定的默認配置信息。幸運的是,幾乎所有默認行為都能通過一組全局參數進行自定義,它們可以管理圖像大小、subplot邊距、配色方案、字體大小、網格類型等。一種Python編程方式配置系統的方法是使用rc方法。例如,要將全局的圖像默認大小設置為10×10,你可以執行: ```python plt.rc('figure', figsize=(10, 10)) ``` rc的第一個參數是希望自定義的對象,如'figure'、'axes'、'xtick'、'ytick'、'grid'、'legend'等。其后可以跟上一系列的關鍵字參數。一個簡單的辦法是將這些選項寫成一個字典: ```python font_options = {'family' : 'monospace', 'weight' : 'bold', 'size' : 'small'} plt.rc('font', **font_options) ``` 要了解全部的自定義選項,請查閱matplotlib的配置文件matplotlibrc(位于matplotlib/mpl-data目錄中)。如果對該文件進行了自定義,并將其放在你自己的.matplotlibrc目錄中,則每次使用matplotlib時就會加載該文件。 下一節,我們會看到,seaborn包有若干內置的繪圖主題或類型,它們使用了matplotlib的內部配置。 # 9.2 使用pandas和seaborn繪圖 matplotlib實際上是一種比較低級的工具。要繪制一張圖表,你組裝一些基本組件就行:數據展示(即圖表類型:線型圖、柱狀圖、盒形圖、散布圖、等值線圖等)、圖例、標題、刻度標簽以及其他注解型信息。 在pandas中,我們有多列數據,還有行和列標簽。pandas自身就有內置的方法,用于簡化從DataFrame和Series繪制圖形。另一個庫seaborn(https://seaborn.pydata.org/),由Michael Waskom創建的靜態圖形庫。Seaborn簡化了許多常見可視類型的創建。 >提示:引入seaborn會修改matplotlib默認的顏色方案和繪圖類型,以提高可讀性和美觀度。即使你不使用seaborn API,你可能也會引入seaborn,作為提高美觀度和繪制常見matplotlib圖形的簡化方法。 ## 線型圖 Series和DataFrame都有一個用于生成各類圖表的plot方法。默認情況下,它們所生成的是線型圖(如圖9-13所示): ```python In [60]: s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10)) In [61]: s.plot() ``` ![圖9-13 簡單的Series圖表示例](https://img.kancloud.cn/36/f4/36f4b3052476c14caaea521ce958b3ff_1240x754.png) 該Series對象的索引會被傳給matplotlib,并用以繪制X軸。可以通過use_index=False禁用該功能。X軸的刻度和界限可以通過xticks和xlim選項進行調節,Y軸就用yticks和ylim。plot參數的完整列表請參見表9-3。我只會講解其中幾個,剩下的就留給讀者自己去研究了。 ![](https://img.kancloud.cn/ca/ce/cace8e721e0563161ca5575688ae4a42_554x148.png) ![表9-3 Series.plot方法的參數](https://img.kancloud.cn/cc/d5/ccd5c8ee3512578689a3d146fb017d42_554x253.png) pandas的大部分繪圖方法都有一個可選的ax參數,它可以是一個matplotlib的subplot對象。這使你能夠在網格布局中更為靈活地處理subplot的位置。 DataFrame的plot方法會在一個subplot中為各列繪制一條線,并自動創建圖例(如圖9-14所示): ```python In [62]: df = pd.DataFrame(np.random.randn(10, 4).cumsum(0), ....: columns=['A', 'B', 'C', 'D'], ....: index=np.arange(0, 100, 10)) In [63]: df.plot() ``` ![圖9-14 簡單的DataFrame繪圖](https://img.kancloud.cn/08/ad/08ad2e48fd881ea7dec72d19be8e66ac_1233x761.png) plot屬性包含一批不同繪圖類型的方法。例如,df.plot()等價于df.plot.line()。后面會學習這些方法。 >筆記:plot的其他關鍵字參數會被傳給相應的matplotlib繪圖函數,所以要更深入地自定義圖表,就必須學習更多有關matplotlib API的知識。 DataFrame還有一些用于對列進行靈活處理的選項,例如,是要將所有列都繪制到一個subplot中還是創建各自的subplot。詳細信息請參見表9-4。 ![表9-4 專用于DataFrame的plot參數](https://img.kancloud.cn/ae/82/ae82be09fcf1c945c84d848f6fedf324_554x214.png) >注意: 有關時間序列的繪圖,請見第11章。 ## 柱狀圖 plot.bar()和plot.barh()分別繪制水平和垂直的柱狀圖。這時,Series和DataFrame的索引將會被用作X(bar)或Y(barh)刻度(如圖9-15所示): ```python In [64]: fig, axes = plt.subplots(2, 1) In [65]: data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop')) In [66]: data.plot.bar(ax=axes[0], color='k', alpha=0.7) Out[66]: <matplotlib.axes._subplots.AxesSubplot at 0x7fb62493d470> In [67]: data.plot.barh(ax=axes[1], color='k', alpha=0.7) ``` ![圖9-15 水平和垂直的柱狀圖](https://img.kancloud.cn/c5/f7/c5f787715b2aeb5ca4ae28de99e1498a_1240x759.png) color='k'和alpha=0.7設定了圖形的顏色為黑色,并使用部分的填充透明度。對于DataFrame,柱狀圖會將每一行的值分為一組,并排顯示,如圖9-16所示: ```python In [69]: df = pd.DataFrame(np.random.rand(6, 4), ....: index=['one', 'two', 'three', 'four', 'five', 'six'], ....: columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus')) In [70]: df Out[70]: Genus A B C D one 0.370670 0.602792 0.229159 0.486744 two 0.420082 0.571653 0.049024 0.880592 three 0.814568 0.277160 0.880316 0.431326 four 0.374020 0.899420 0.460304 0.100843 five 0.433270 0.125107 0.494675 0.961825 six 0.601648 0.478576 0.205690 0.560547 In [71]: df.plot.bar() ``` ![圖9-16 DataFrame的柱狀圖](https://img.kancloud.cn/3c/10/3c103d9e0241f1e66bc1020e726f81da_1240x794.png) 注意,DataFrame各列的名稱"Genus"被用作了圖例的標題。 設置stacked=True即可為DataFrame生成堆積柱狀圖,這樣每行的值就會被堆積在一起(如圖9-17所示): ```python In [73]: df.plot.barh(stacked=True, alpha=0.5) ``` ![圖9-17 DataFrame的堆積柱狀圖](https://img.kancloud.cn/0a/67/0a679742f784ac13439cf213d47bd4ce_1240x744.png) >筆記:柱狀圖有一個非常不錯的用法:利用value_counts圖形化顯示Series中各值的出現頻率,比如s.value_counts().plot.bar()。 再以本書前面用過的那個有關小費的數據集為例,假設我們想要做一張堆積柱狀圖以展示每天各種聚會規模的數據點的百分比。我用read_csv將數據加載進來,然后根據日期和聚會規模創建一張交叉表: ```python In [75]: tips = pd.read_csv('examples/tips.csv') In [76]: party_counts = pd.crosstab(tips['day'], tips['size']) In [77]: party_counts Out[77]: size 1 2 3 4 5 6 day Fri 1 16 1 1 0 0 Sat 2 53 18 13 1 0 Sun 0 39 15 18 3 1 Thur 1 48 4 5 1 3 # Not many 1- and 6-person parties In [78]: party_counts = party_counts.loc[:, 2:5] ``` 然后進行規格化,使得各行的和為1,并生成圖表(如圖9-18所示): ```python # Normalize to sum to 1 In [79]: party_pcts = party_counts.div(party_counts.sum(1), axis=0) In [80]: party_pcts Out[80]: size 2 3 4 5 day Fri 0.888889 0.055556 0.055556 0.000000 Sat 0.623529 0.211765 0.152941 0.011765 Sun 0.520000 0.200000 0.240000 0.040000 Thur 0.827586 0.068966 0.086207 0.017241 In [81]: party_pcts.plot.bar() ``` ![圖9-18 每天各種聚會規模的比例](https://img.kancloud.cn/ae/4a/ae4ad4aab32a0a192001474a283c5267_1240x815.png) 于是,通過該數據集就可以看出,聚會規模在周末會變大。 對于在繪制一個圖形之前,需要進行合計的數據,使用seaborn可以減少工作量。用seaborn來看每天的小費比例(圖9-19是結果): ```python In [83]: import seaborn as sns In [84]: tips['tip_pct'] = tips['tip'] / (tips['total_bill'] - tips['tip']) In [85]: tips.head() Out[85]: total_bill tip smoker day time size tip_pct 0 16.99 1.01 No Sun Dinner 2 0.063204 1 10.34 1.66 No Sun Dinner 3 0.191244 2 21.01 3.50 No Sun Dinner 3 0.199886 3 23.68 3.31 No Sun Dinner 2 0.162494 4 24.59 3.61 No Sun Dinner 4 0.172069 In [86]: sns.barplot(x='tip_pct', y='day', data=tips, orient='h') ``` ![圖9-19 小費的每日比例,帶有誤差條](https://img.kancloud.cn/dc/d6/dcd6dd5330dd54bf4282932ead998be8_1240x762.png) seaborn的繪制函數使用data參數,它可能是pandas的DataFrame。其它的參數是關于列的名字。因為一天的每個值有多次觀察,柱狀圖的值是tip_pct的平均值。繪制在柱狀圖上的黑線代表95%置信區間(可以通過可選參數配置)。 seaborn.barplot有顏色選項,使我們能夠通過一個額外的值設置(見圖9-20): ```python In [88]: sns.barplot(x='tip_pct', y='day', hue='time', data=tips, orient='h') ``` ![圖9-20 根據天和時間的小費比例](https://img.kancloud.cn/e0/bf/e0bf8a60846b304b1a83599ac10abe7a_1240x762.png) 注意,seaborn已經自動修改了圖形的美觀度:默認調色板,圖形背景和網格線的顏色。你可以用seaborn.set在不同的圖形外觀之間切換: ```python In [90]: sns.set(style="whitegrid") ``` ## 直方圖和密度圖 直方圖(histogram)是一種可以對值頻率進行離散化顯示的柱狀圖。數據點被拆分到離散的、間隔均勻的面元中,繪制的是各面元中數據點的數量。再以前面那個小費數據為例,通過在Series使用plot.hist方法,我們可以生成一張“小費占消費總額百分比”的直方圖(如圖9-21所示): ```python In [92]: tips['tip_pct'].plot.hist(bins=50) ``` ![圖9-21 小費百分比的直方圖](https://img.kancloud.cn/d9/0a/d90a4a96b398181bd1d1ec22ec3e3ebb_1240x742.png) 與此相關的一種圖表類型是密度圖,它是通過計算“可能會產生觀測數據的連續概率分布的估計”而產生的。一般的過程是將該分布近似為一組核(即諸如正態分布之類的較為簡單的分布)。因此,密度圖也被稱作KDE(Kernel Density Estimate,核密度估計)圖。使用plot.kde和標準混合正態分布估計即可生成一張密度圖(見圖9-22): ```python In [94]: tips['tip_pct'].plot.density() ``` ![圖9-22 小費百分比的密度圖](https://img.kancloud.cn/ef/c9/efc91759bb86b4a97081b09fa77115fe_1240x750.png) seaborn的distplot方法繪制直方圖和密度圖更加簡單,還可以同時畫出直方圖和連續密度估計圖。作為例子,考慮一個雙峰分布,由兩個不同的標準正態分布組成(見圖9-23): ```python In [96]: comp1 = np.random.normal(0, 1, size=200) In [97]: comp2 = np.random.normal(10, 2, size=200) In [98]: values = pd.Series(np.concatenate([comp1, comp2])) In [99]: sns.distplot(values, bins=100, color='k') ``` ![圖9-23 標準混合密度估計的標準直方圖](https://img.kancloud.cn/ca/76/ca7689a9d050239b5cbd39fa1edbed6a_1240x749.png) ## 散布圖或點圖 點圖或散布圖是觀察兩個一維數據序列之間的關系的有效手段。在下面這個例子中,我加載了來自statsmodels項目的macrodata數據集,選擇了幾個變量,然后計算對數差: ```python In [100]: macro = pd.read_csv('examples/macrodata.csv') In [101]: data = macro[['cpi', 'm1', 'tbilrate', 'unemp']] In [102]: trans_data = np.log(data).diff().dropna() In [103]: trans_data[-5:] Out[103]: cpi m1 tbilrate unemp 198 -0.007904 0.045361 -0.396881 0.105361 199 -0.021979 0.066753 -2.277267 0.139762 200 0.002340 0.010286 0.606136 0.160343 201 0.008419 0.037461 -0.200671 0.127339 202 0.008894 0.012202 -0.405465 0.042560 ``` 然后可以使用seaborn的regplot方法,它可以做一個散布圖,并加上一條線性回歸的線(見圖9-24): ```python In [105]: sns.regplot('m1', 'unemp', data=trans_data) Out[105]: <matplotlib.axes._subplots.AxesSubplot at 0x7fb613720be0> In [106]: plt.title('Changes in log %s versus log %s' % ('m1', 'unemp')) ``` ![圖9-24 seaborn的回歸/散布圖](https://img.kancloud.cn/60/46/604658986a9f5dbc0d9a814a7f7b15f0_1240x781.png) 在探索式數據分析工作中,同時觀察一組變量的散布圖是很有意義的,這也被稱為散布圖矩陣(scatter plot matrix)。純手工創建這樣的圖表很費工夫,所以seaborn提供了一個便捷的pairplot函數,它支持在對角線上放置每個變量的直方圖或密度估計(見圖9-25): ```python In [107]: sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2}) ``` ![圖9-25 statsmodels macro data的散布圖矩陣](https://img.kancloud.cn/a6/23/a62351a2d041a0fc45e18456399a5f56_1240x1226.png) 你可能注意到了plot_kws參數。它可以讓我們傳遞配置選項到非對角線元素上的圖形使用。對于更詳細的配置選項,可以查閱seaborn.pairplot文檔字符串。 ##分面網格(facet grid)和類型數據 要是數據集有額外的分組維度呢?有多個分類變量的數據可視化的一種方法是使用小面網格。seaborn有一個有用的內置函數factorplot,可以簡化制作多種分面圖(見圖9-26): ```python In [108]: sns.factorplot(x='day', y='tip_pct', hue='time', col='smoker', .....: kind='bar', data=tips[tips.tip_pct < 1]) ``` ![圖9-26 按照天/時間/吸煙者的小費百分比](https://img.kancloud.cn/24/a5/24a5ca0f0474938864657909756d24be_1240x540.png) 除了在分面中用不同的顏色按時間分組,我們還可以通過給每個時間值添加一行來擴展分面網格: ```python In [109]: sns.factorplot(x='day', y='tip_pct', row='time', .....: col='smoker', .....: kind='bar', data=tips[tips.tip_pct < 1]) ``` ![圖9-27 按天的tip_pct,通過time/smoker分面](https://img.kancloud.cn/a5/bf/a5bf8071d9894493a39decd1f5aa8132_1174x1175.png) factorplot支持其它的繪圖類型,你可能會用到。例如,盒圖(它可以顯示中位數,四分位數,和異常值)就是一個有用的可視化類型(見圖9-28): ```python In [110]: sns.factorplot(x='tip_pct', y='day', kind='box', .....: data=tips[tips.tip_pct < 0.5]) ``` ![圖9-28 按天的tip_pct的盒圖](https://img.kancloud.cn/50/0b/500b04921d26d60757c2354a4b9355b0_577x573.png) 使用更通用的seaborn.FacetGrid類,你可以創建自己的分面網格。請查閱seaborn的文檔(https://seaborn.pydata.org/)。 # 9.3 其它的Python可視化工具 與其它開源庫類似,Python創建圖形的方式非常多(根本羅列不完)。自從2010年,許多開發工作都集中在創建交互式圖形以便在Web上發布。利用工具如Boken(https://bokeh.pydata.org/en/latest/)和Plotly(https://github.com/plotly/plotly.py),現在可以創建動態交互圖形,用于網頁瀏覽器。 對于創建用于打印或網頁的靜態圖形,我建議默認使用matplotlib和附加的庫,比如pandas和seaborn。對于其它數據可視化要求,學習其它的可用工具可能是有用的。我鼓勵你探索繪圖的生態系統,因為它將持續發展。 # 9.4 總結 本章的目的是熟悉一些基本的數據可視化操作,使用pandas,matplotlib,和seaborn。如果視覺顯示數據分析的結果對你的工作很重要,我鼓勵你尋求更多的資源來了解更高效的數據可視化。這是一個活躍的研究領域,你可以通過在線和紙質的形式學習許多優秀的資源。 下一章,我們將重點放在pandas的數據聚合和分組操作上。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看