# 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裡面繪畫,並且由於有能力進行手刻,任意統計圖理論上都能畫出來了! * 現在你的整個資料分析流程又包含了繪圖了,之後再讓我們學一些更強的功能吧!