---
# System prepended metadata

title: Lesson 9 | 簡易繪圖功能

---

# Lesson 9 | 簡易繪圖功能
## 第一節：基礎繪圖函數簡介-1(1)

* 在清理完資料後，我們可以透過視覺化的方式來做資料探勘，同樣的資訊，使用圖像相呈現較於表格/文字，通常能讓閱讀者更快的獲得資訊。

* 相信同學們對安裝套件已經不陌生，在這堂課將帶著同學們使用常見的第三方套件[Matplotlib](https://matplotlib.org/)進行視覺化，我們可以在其[官方網站](https://matplotlib.org/stable/users/getting_started/)看到安裝說明。

![L9-1](https://i.imgur.com/1O9F06q.png)

* 安裝成功後，我們試著載入Matplotlib套件。
    
    ```python=
    import matplotlib.pyplot as plt
    import numpy as np

    x = np.linspace(0, 2 * np.pi, 200)
    y = np.sin(x)

    fig, ax = plt.subplots()
    ax.plot(x, y)
    ```

## 第一節：基礎繪圖函數簡介-1(2)

* ```Matplotlib```要怎麼畫圖呢？我們可以以這樣的方式去載入模組，並用```subplots```來先宣告我們的圖(```Figure```)跟可以放入資料的軸(```Axes```)。

    ```python=
    # 在Jupyter裡面，圖會被自動化出。 
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3, 4], [1, 4, 2, 3]) 
    ```
    
    ```python=
    # 你也可以呼叫fig這個物件來顯示圖。
    fig
    ```

## 第一節：基礎繪圖函數簡介-1(3)

* 讓我們來透過視覺化來探勘[這個](https://linchin.ndmctsgh.edu.tw/data/Example_data.csv)模擬的醫學資料吧，請先下載！

* 可以使用```Pandas```套件將資料讀進Python。

    ```python=
    import pandas as pd
    data = pd.read_csv("Example_data.csv")
    data
    ```    
    
* 讓我們先從幾個簡單的統計圖開始，記得要先去除NA值。

    1. 直方圖：需要使用函數「.hist()」
    
        ```python=
        fig, ax = plt.subplots()
        clean_eGFR = data['eGFR'][pd.isnull(data['eGFR']) == False]
        ax.hist(clean_eGFR)
        ```
    
    2. 盒鬚圖：需要使用函數「.boxplot()」
    
        ```python=
        fig, ax = plt.subplots()
        clean_eGFR = data['eGFR'][pd.isnull(data['eGFR']) == False]
        ax.boxplot(clean_eGFR)
        ```
    
    3. 圓餅圖：需要使用函數「.pie()」以及```pandas```的函數「.value_counts()」
    
        ```python=
        fig, ax = plt.subplots()
        clean_edu = data['Education'][pd.isnull(data['Education']) == False]
        ax.pie(pd.value_counts(clean_edu))
        ```
    
    4. 長條圖：需要使用函數「.barplot()」以及```pandas```的函數「.value_counts()」

        ```python=
        fig, ax = plt.subplots()
        clean_edu = data['Education'][pd.isnull(data['Education']) == False]
        ax.bar(list(set(clean_edu)), pd.value_counts(clean_edu))
        ```
        
## 第一節：基礎繪圖函數簡介-1(4)

* 這些圖都能透過增加不同的參數增加變化，我們可以透過[官方說明文件](https://matplotlib.org/stable/api/index.html)來查詢它們內部的參數。舉例來說，我們可以用下列方式改變圖的顏色

    - 在[這裡](https://matplotlib.org/stable/gallery/color/named_colors.html)，我們可以看到關於顏色的說明。
    
    - 另外，我們可以用這樣的方式，把4張圖放在同一張畫布內：
    
        ```python=
        clean_eGFR = data['eGFR'][pd.isnull(data['eGFR']) == False]
        clean_edu = data['Education'][pd.isnull(data['Education']) == False]

        fig, ax = plt.subplots(2, 2)
        ax[0,0].hist(clean_eGFR, color = 'purple')
        ax[0,1].boxplot(clean_eGFR, boxprops = {'color': 'blue'})
        ax[1,0].pie(pd.value_counts(clean_edu), colors = ['yellow', 'green', 'black'])
        ax[1,1].bar(list(set(clean_edu)), pd.value_counts(clean_edu), color = 'red')
        ```

* 你如果喜歡你畫的圖，可以透過```Figure```的方法「.savefig()」把圖片存出去。

    ```python=
    fig.savefig("test.pdf")
    ```
    
## 練習1：

* 請練習看[官方說明文件](https://matplotlib.org/stable/api/index.html#)，查詢該如何完成下面這張圖：

    ![L9-2](https://i.imgur.com/ijmBuMj.png)


    <details>
  <summary>解答</summary>
    
    - 你可以在[這裡](https://matplotlib.org/stable/gallery/statistics/boxplot_demo.html#boxplots)找到範例程式碼，可以發現輸入參數使用能儲存多筆資料的```list```即可。
    
    - 關於軸的設定可以在[這裡](https://matplotlib.org/stable/tutorials/introductory/quick_start.html#axes)找到。

        ```python=
        # 資料前處理的熟悉度也是相當重要的。
        eGFR_0 = data['eGFR'][data['Disease'] == 0]
        eGFR_1 = data['eGFR'][data['Disease'] == 1]

        eGFR_0 = eGFR_0[pd.isna(eGFR_0) == False]
        eGFR_1 = eGFR_1[pd.isna(eGFR_1) == False]

        fig, ax = plt.subplots()
        ax.boxplot(
            [eGFR_0, eGFR_1], labels = [0, 1], 
            boxprops = {'color': 'blue'}
        )
        ax.set_title("eGFR value by Disease status")
        ax.set_ylabel("eGFR")
        ax.set_xlabel("Disease")
        ```

    </details>

## 第二節：基礎繪圖函數簡介-2(1)

* 接著我們介紹一個強大的函數「.plot()」，他支援了多種不同的圖形，其中最主要的是散布圖：

    ```python=
    SBP = data['SBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)]
    DBP = data['DBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)]

    fig, ax = plt.subplots()
    ax.plot(SBP, DBP, 'o')
    ax.set_title("Scatter plot of SBP and DBP")
    ax.set_ylabel("DBP")
    ax.set_xlabel("SBP")
    ```

* 其實，我們可以修改點的造型，例如：

    ```python=
    SBP = data['SBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)]
    DBP = data['DBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)]

    fig, ax = plt.subplots()
    ax.plot(SBP, DBP, '4g')
    ax.set_title("Scatter plot of SBP and DBP")
    ax.set_ylabel("DBP")
    ax.set_xlabel("SBP")
    ```

* 這樣的設定來自於第三個參數```fmt(Format Strings)```，請看[這裡](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html#matplotlib.axes.Axes.plot)可以找到相關說明。

    ![L9-3](https://i.imgur.com/taTrbqM.png)

## 第二節：基礎繪圖函數簡介-2(2)

* 你也可以利用```.plot()```為你的圖形加點東西，例如畫線可以將fmt設為```'-'```：

    ```python=
    x = [1, 4, 7]
    y = [2, 9, 6]
    
    fig, ax = plt.subplots()
    ax.plot(x, y, '-')
    ```
    
* 當然，如果點夠密，你其實可以畫出圓！

    ```python=
    import numpy as np
    z = np.array(list(range(1001)))/100
    x = np.sin(z)
    y = np.cos(z)

    fig, ax = plt.subplots()
    ax.plot(x, y, '-')
    ```

## 第二節：基礎繪圖函數簡介-2(3)

* 學會如何畫線以後，我們能夠幫散布圖上加預測線了…

    * 我們需要先畫出預測線，這時需要靠第三方套件幫忙，在Python裡[scikit-learn](https://scikit-learn.org/stable/)是最常用來做數據分析以及機器學習的功能強大套件請先安裝：
    
    ![L9-4](https://i.imgur.com/yK06mut.png)
    
    * 接著，預測線的方程式，需要函數「lm()」幫忙建立。
    
        ```python=
        from sklearn.linear_model import LinearRegression

        SBP = data['SBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)].to_numpy()
        DBP = data['DBP'][(pd.isna(data['SBP']) == False) & (pd.isna(data['DBP']) == False)].to_numpy()

        SBP = SBP.reshape((SBP.shape[0], 1))

        reg = LinearRegression().fit(SBP, DBP)
        coef = reg.coef_, reg.intercept_

        pred_DBP = SBP * reg.coef_[0] + reg.intercept_
        ```
    
    * 並把圖畫出：

        ```python=
        fig, ax = plt.subplots()
        ax.plot(SBP, DBP, 'ok')
        ax.plot(SBP, pred_DBP, '-r')
        ax.set_title("Scatter plot of SBP and DBP")
        ax.set_ylabel("DBP")
        ax.set_xlabel("SBP")
        ```
        
## 第二節：基礎繪圖函數簡介-2(4)

* 其實，你還可以為你的圖形加點料…

    1. 「text()」可以為你的圖片上加文字描述

        ```python=
        x = (np.array([1, 0, -1, 0])/5) + 0.5
        y = (np.array([0, 1, 0, -1])/5) + 0.5
        t = ["A", "B", "C", "D"]

        fig, ax = plt.subplots()
        for i in range(len(x)):
            ax.text(x[i], y[i], t[i])
        ```
        
    2. 「legend()」可以產生註釋，看[這裡](https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html)有更多的說明。

        ```python=
        fig, axs = plt.subplots()

        axs.plot([0, 1, 2], [1, 2, 3], label="test1")
        axs.plot([0, 1, 2], [3, 2, 1], label="test2")

        # Place a legend to the right of this smaller subplot.
        fig.legend(loc='outside upper right')
        ```
        
## 練習2：

* 你已經會畫長條圖了吧? 請你畫出下面這張圖！

    ![L9-5](https://i.imgur.com/cUA9zN0.png)

    * 資料前處理可以參考以下，兩組檢定後的*p*-value為0.020。
    
        ```python=
        eGFR_0 = data['eGFR'][data['Disease'] == 0]
        eGFR_1 = data['eGFR'][data['Disease'] == 1]

        eGFR_0 = eGFR_0[pd.isna(eGFR_0) == False]
        eGFR_1 = eGFR_1[pd.isna(eGFR_1) == False]

        m0 = np.mean(eGFR_0)
        m1 = np.mean(eGFR_1)

        sd0 = np.std(eGFR_0)/(sum(data['Disease'] == 0) ** 0.5)
        sd1 = np.std(eGFR_1)/(sum(data['Disease'] == 1) ** 0.5)
        ```

    <details>
  <summary>解答</summary>
    
    ```python=
    fig, ax = plt.subplots()

    ax.bar("Disease 0", m0, label="Case")
    ax.bar("Disease 1", m1, label="Control")

    ax.plot([-0.25, 0.25], [m0 - (1.96 * sd0), m0 - (1.96 * sd0)], '-k')
    ax.plot([-0.25, 0.25], [m0 + (1.96 * sd0), m0 + (1.96 * sd0)], '-k')
    ax.plot([0, 0], [m0 - (1.96 * sd0), m0 + (1.96 * sd0)], '-k')

    ax.plot([0.75, 1.25], [m1 - (1.96 * sd1), m1 - (1.96 * sd1)], '-k')
    ax.plot([0.75, 1.25], [m1 + (1.96 * sd1), m1 + (1.96 * sd1)], '-k')
    ax.plot([1.00, 1.00], [m1 - (1.96 * sd1), m1 + (1.96 * sd1)], '-k')

    ax.plot([0, 0, 1, 1], [35, 38, 38, 36], '-k')
    ax.text(0.35, 38.5, 'p = 0.020')
    ax.set_ylabel("eGFR")

    fig.legend(loc='outside upper right')
    ```
    
    </details>
    
## 總結
                                           
* 本週介紹了簡易的繪圖功能，這讓我們能在Python裡面繪畫，並且由於有能力進行手刻，任意統計圖理論上都能畫出來了！

* 現在你的整個資料分析流程又包含了繪圖了，之後再讓我們學一些更強的功能吧！