---
# System prepended metadata

title: Lab12：數據資料視覺化

---

# Lab12：數據資料視覺化

## 注意
這次的lab可以選在電腦或是樹梅派上完成
## Matplotlib
### 介紹
![image](https://hackmd.io/_uploads/S1IonxVI6.png)

在大數據應用的時代，除了將資料分析後的結果具體呈現之外，總希望可以在整個分析過程當中利用資料視覺化來看出一些有趣及重要的insight，尤其在大數據下的機器學習及人工智慧應用更是重要。
![image](https://hackmd.io/_uploads/HkN0GFWUa.png)
![image](https://hackmd.io/_uploads/Hk9jMtWUp.png)




### install
```pip install matplotlib```

創一個test.py打上
```python=
import matplotlib.pyplot as plt
```
執行他，如果沒事就沒問題!

* 如果遇到
* ![](https://i.imgur.com/7HyHUmR.png)

```python=
pip uninstall matplotlib #如果你已經安裝過，若沒有則跳過
pip install numpy --upgrade --ignore-installed
sudo apt-get install libatlas-base-dev
pip install matplotlib	#安裝 Matplotlib
```
<font color='red' size='20'>如果你連線到樹梅派操作plt.show()沒用</font>
<font color='red' size='20'>請把每張圖片用 plt.savefig()存下來後，點開來看 </font>


<!-- ### example data
梅西、C羅 2005-2021的國家隊比賽數據 (維基百科寫的)
https://zh.wikipedia.org/zh-tw/%E5%88%A9%E6%98%82%E5%86%85%E5%B0%94%C2%B7%E6%A2%85%E8%A5%BF
https://zh.m.wikipedia.org/zh-tw/%E5%9F%BA%E6%96%AF%E5%9D%A6%E5%A5%B4%C2%B7%E6%9C%97%E6%8B%BF%E5%BA%A6
```python=
Messi_goal = [0,2,6,2,3,2,4,12,6,8,4,8,4,4,5,1,9,14] #進球數
Messi_play = [5,7,14,8,10,10,13,9,7,14,8,11,7,5,10,4,16,11] #上場數
C_goal  = [0,7,2,6,5,1,3,7,5,10,5,3,13,11,6,14,3,7] #進球數
C_play = [2,16,11,14,10,8,7,11,8,13,9,9,5,13,11,7,10,6,8] #上場數
``` -->

## numpy
![image](https://hackmd.io/_uploads/H1amAo78p.png)

NumPy，全名為 Numeric Python，是一個開源的 Python 函式庫，用於在 Python 中進行科學計算。它提供了一個強大的 N 維陣列對象，豐富的廣播功能，以及各種數學、邏輯、形狀操作、排序、選擇、I/O、離散傅立葉變換、基本線性代數、基本統計運算和隨機模擬等功能。NumPy 是許多高階科學計算包的核心，如 SciPy、Pandas、Matplotlib、scikit-learn 等，這些包在資料分析、機器學習等領域非常受歡迎。

高效能的多維陣列（ndarray）：NumPy 的核心是多維陣列對象。這是一種強大的數據結構，能夠讓你進行高效的向量化計算、廣播等操作。
集成 C/C++ 和 Fortran 代碼的能力：NumPy 可以很方便地和 C/C++ 或 Fortran 代碼集成，這對於需要優化性能的重計算任務來說非常重要。

原本python的list -> 速度慢
numpy -> 速度快

### 下載
```pip install numpy ```

### np.linespace()
Numpy 中的 linspace 函數可以在一定範圍內來均勻地撒點


```python=
import numpy as np
a = np.linspace(1, 3, 3) #在1-3之間產生3個點
print(a)
# [ 1.  2.  3.]

b = np.linspace(1, 5, 20) #在1-5之間產生20個點
print(b)
# [1.         1.21052632 1.42105263 1.63157895 1.84210526 2.05263158
#  2.26315789 2.47368421 2.68421053 2.89473684 3.10526316 3.31578947
#  3.52631579 3.73684211 3.94736842 4.15789474 4.36842105 4.57894737
#  4.78947368 5.        ]
print(type(b))
#<class 'numpy.ndarray'>
```

### 圖表的構成
![](https://i.imgur.com/hVbPJ3D.png)
* Figure: 指的是畫布，也就是當我們要畫圖時，要先創建一個畫布，才能在上面加上各種圖片(元素)
* Axes: 代表的則是紙中的其中一片區域(可能有很多子圖)
* Axis: 指x, y軸(or z軸 3維時)

### scatter 散點圖
```python=
x = np.linspace(0, 10, 20)
y = np.sin(x) # sin函數
plt.scatter(x, y) # 繪製散點圖
plt.title('Scatter Plot')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
```
![](https://i.imgur.com/j1RwoQ6.png)



### plot 折線圖

```python=
# 繪製直線
x = np.linspace(0, 10, 20)
x2 = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x2)
plt.plot(x, y1, label='y1')
plt.plot(x2, y2, label='y2')
plt.title('Scatter Plot')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
```

![image](https://hackmd.io/_uploads/H1RPvtb8p.png)


### plt.legend()

![image](https://hackmd.io/_uploads/rJp4ue4Ua.png)



梅西、C羅 2005-2021的國家隊比賽數據 (維基百科寫的)
https://zh.wikipedia.org/zh-tw/%E5%88%A9%E6%98%82%E5%86%85%E5%B0%94%C2%B7%E6%A2%85%E8%A5%BF
https://zh.m.wikipedia.org/zh-tw/%E5%9F%BA%E6%96%AF%E5%9D%A6%E5%A5%B4%C2%B7%E6%9C%97%E6%8B%BF%E5%BA%A6
```python=
Messi_goal = [0,2,6,2,3,2,4,12,6,8,4,8,4,4,5,1,9,14] #進球數
Messi_play = [5,7,14,8,10,10,13,9,7,14,8,11,7,5,10,4,16,11] #上場數
C_goal  = [0,7,2,6,5,1,3,7,5,10,5,3,13,11,6,14,3,7] #進球數
C_play = [2,16,11,14,10,8,7,11,8,13,9,9,5,13,11,7,10,6,8] #上場數

years = np.array(range(2005,2023))
# years = np.arange(2005,2022)
print(years)
# [2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022]

plt.plot(years, Messi_goal, '-o', label='Messi')
plt.plot(years, C_goal, '-*', label='C.Ronaldo')
plt.title('Messi v.s. C.Ronaldo')
plt.xlabel('years')
plt.ylabel('goals')
plt.legend()
plt.show()
```
![](https://i.imgur.com/QqTrUvl.png)



### hist直方圖
```python=
plt.hist( Messi_goal, label='Messi')
plt.hist(C_goal, label='C.Ronaldo')
plt.title('Messi v.s. C.Ronaldo')
plt.xlabel('years')
plt.ylabel('goals')
plt.legend()
plt.show()
```
![](https://i.imgur.com/sorUJWe.png)



### bar長條圖
#### enumerate: 同時輸出索引與元素
```python=
List = ['a', 'b', 'c', 'd', 'e']

for value in enumerate(List):
    print(value)

# (0, 'a')
# (1, 'b')
# (2, 'c')
# (3, 'd')
# (4, 'e')
```
```python=
List = ['a', 'b', 'c', 'd', 'e']

for index, element in enumerate(List):
    print(f"Index: {index}, Element: {element}")
# Index: 0, Element: a
# Index: 1, Element: b
# Index: 2, Element: c
# Index: 3, Element: d
# Index: 4, Element: e
```

```python=
Messi_total = sum(Messi_goal) # 計算總進球數
C_goal_total = sum(C_goal)
total_list = [Messi_total, C_goal_total]
ind = np.arange(len(total_list))
plt.xticks(ind, ['Messi', 'C.Ronaldo']) #指定x軸座標軸
plt.bar(ind, total_list)
plt.title("Messi v.s. C.Ronaldo total goals")

for index, data in enumerate(total_list):
    plt.text(x = index, y =data, s=data, horizontalalignment='center', fontsize=15)
    
plt.show()
# horizontalalignment: 水平位置
# verticalalignment: 垂直位置
```
![image](https://hackmd.io/_uploads/rJYL2-NLa.png)



### subplot 子圖
使用 subplot()的方法建立子圖表時，會按照 row ( 垂直 )、column ( 水平 ) 的矩陣方式，將子圖表放入對應的位置，下圖表示擁有 3x3 和 3x2 個子圖表的畫布，各個子圖表的 index ( 位置 ) 和排列順序。
![](https://i.imgur.com/ksZLMyw.png)
```python=
fig = plt.figure(figsize=(8,6))
fig.add_subplot(2, 2, 1)#建立2 x 2的子圖
plt.subplot(2, 2, 1) # 繪製第1個位置
x = np.linspace(0, 10, 20)
y = np.sin(x)
plt.scatter(x, y)
plt.title('Scatter Plot')
plt.xlabel('x')
plt.ylabel('y')

plt.subplot(2, 2, 2) # 繪製第2個位置
plt.plot(years, Messi_goal, '-o', label='Messi')
plt.plot(years, C_goal, '-*', label='C.Ronaldo')
plt.title('Messi v.s. C.Ronaldo')
plt.xlabel('years')
plt.ylabel('goals')
plt.legend()

plt.subplot(2, 2, 3) # 繪製第3個位置
plt.hist( Messi_goal, label='Messi')
plt.hist(C_goal, label='C.Ronaldo')
plt.title('Messi v.s. C.Ronaldo')
plt.xlabel('years')
plt.ylabel('goals')
plt.legend()

plt.subplot(2, 2, 4) # 繪製第4個位置
Messi_total = sum(Messi_goal) # 計算總進球數
C_goal_total = sum(C_goal)
total_list = [Messi_total, C_goal_total]
ind = np.arange(len(total_list))
plt.xticks(ind, ['Messi', 'C.Ronaldo']) #指定x軸座標軸
plt.bar(ind, total_list)
plt.title("Messi v.s. C.Ronaldo total goals")

for index, data in enumerate(total_list):
    plt.text(x = index, y =data, s=data, horizontalalignment='center', fontsize=15)

fig.suptitle('subplot example ', fontsize=16)
plt.tight_layout() #讓子圖之間適當排列不重疊
plt.show()
```
![](https://i.imgur.com/IJnY7dM.png)


### 儲存圖片
```python=
fig = plt.figure() # 建立圖表
fig.savefig('lab12.png') #儲存圖片
```

### 補充資料
[matplotlib官網](https://matplotlib.org/)
[plt / ax / fig是什麼?怎麼用?](https://chwang12341.medium.com/%E7%A8%8B%E5%BC%8F%E8%A7%80%E5%BF%B5-%E5%A4%A7%E5%AE%B6%E9%83%BD%E6%9C%83%E4%BD%BF%E7%94%A8plt%E7%95%AB%E5%9C%96-%E4%BD%86%E6%98%AF%E4%BD%A0%E7%9C%9F%E7%9A%84%E7%9F%A5%E9%81%93plt-ax-fig%E6%98%AF%E4%BB%80%E9%BA%BC%E5%97%8E-%E6%80%8E%E9%BA%BC%E7%94%A8-6f0bc6404f8f)
[高階python繪圖工具seaborn](https://seaborn.pydata.org/)

    
## Lab12
[Temperature.txt](https://drive.google.com/file/d/1hhtRrYekBfjp-dNCeICUBqtMddV-Gr6q/view?usp=sharing)
檔案中包含了台南的2013-2021的每月溫度資料
下載Temperature.txt到lab12資料夾中，與lab12.py一樣路徑
<font color = 'red'>請搜尋python read txt file來讀取Temperature.txt </font>

```python=

# 資料建議整以下這樣
print(temp_list)

[  # [1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月]
    [17.5, 20.4, 22.5, 23.9, 27.3, 29.5, 29.4, 28.9, 28.6, 25.7, 22.8, 18.0], #2013
........................
    [16.5, 19.7, 22.4, 24.6, 29.0, 28.3, 29.1, 28.4, 29.5, 27.3, 23.2, 19.3] #2021
]
```

1. 將歷年的台南氣溫資料用plt.plot()繪製成如下圖，儲存圖片命名為 lab12_01.png
hint: 可以自己建立一個年份的list，利用for迴圈可以提高撰寫效率
![](https://i.imgur.com/Nzf1Uts.png)

2. 分別計算每個月份每年的氣溫平均值，把12個月份分別的的氣溫平均值繪製成一張表
計算每個月分氣溫的總平均值(全部的平均)，在圖表上繪製一條水平虛線，並且標示總平均值的數字在須線上，儲存圖片命名為 lab12_02.png
![](https://i.imgur.com/R79p5nl.png)

3. 將前面兩張圖片使用subplot(1,2,x)畫在同一張圖片上，儲存圖片命名為 lab12_03.png

```python=
fig = plt.figure(figsize=(15,6))
...
fig.savefig('lab12_03.png')
```
![](https://i.imgur.com/5i9d5ZP.png)

## Lab12加分題
[oddExperiment.txt](https://drive.google.com/file/d/173nbRv8VNZNVOI96Sk_iqLH8iEEL4wUk/view?usp=sharing)

```python=
### 資料前處理

# 讀完的資料會長這樣
[301.8267195898913, 206.48068590297993, ...........139.43161572804308, 281.7900813768265, 229.67424006279856]
[-10, -9, ................. 9, 10]
```

1. 將資料點利用plt.scatter繪製出來
2. 利用np.polyfit與np.poly1d 去找出最符合資料分布的**一階多項式** 以及 **二階多項式**，並且繪製出來
3. 計算資料點的與一階多項式 以及 二階多項式分別的**least square error (mean square error)** 以及，顯示在plt.legend()中
4. 儲存圖片命名為 lab12_plus.png
![image](https://hackmd.io/_uploads/SkoNyGNI6.png)



### 注意事項
* <font color="red">所有圖片的x,y座標，legend位置，圖標顏色、大小、形狀，都要盡量一模一樣，沒有的話會斟酌扣分</font>
* deadline為 12/18(一) 23:59
* 上傳到 GitHub lab12
* Lab12與Lab12加分題請分成兩個檔案上傳，檔名: <a>lab12.py</a>,  lab12_plus.py
* 所有圖片都要一起上傳到github
* 資料夾名稱：「lab12」
    * 程式碼名稱：「lab12.py」, 「lab12_plus.py」
    * 圖片檔案：「lab12_01.png」、「lab12_02.png」、「lab12_03.png」、「lab12_plus.png」


<!-- ### Lab13參考答案
```python=
# read file
with open('Temperature.txt','r') as fh:
    next(fh) #跳過第一行
    linelist = fh.readlines()
    for i in range(len(linelist)):
        linelist[i] = linelist[i].strip() #strip()去除換行字元(\n)和空白字元

onelinelist = []
for i in range(len(linelist)):
    onelinelist.append(linelist[i].split(', ')) #將linelist中每一個元素存成onelinelist每一個row

temp_list = []
for i in range(len(onelinelist)):
    onelinelist[i] = list(map(float, onelinelist[i])) #將資料轉換為float型態
    temp_list.append(onelinelist[i][1:]) #去除年份，只留下每個月的溫度資料

# Lab13_1
for i in range(0,9):
    plt.plot(list(range(1,13)),temp_list[i],label=str(int(year[i])))
    plt.legend(loc = 'lower center')

ax=plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))

plt.xlabel('Month')
plt.ylabel('Temperature in Degree C')
plt.title('Tainan Monthly Mean Temperature From 2013 To 2021')

# Lab13_2
temp = []
temp2 =[]
for j in range(12):
    for i in range(9):
        temp2.append(temp_list[i][j])
        
    temp.append(temp2)
    temp2 =[]
    
degree = []
for i in range(12):
    degree.append(np.mean(temp[i]))
    
    
plt.plot(list(range(1,13)),degree) #, marker='o',  markerfacecolor='r', markersize=5
plt.scatter(list(range(1,13)),degree, c='red', alpha=1)
for i in range(12):
    plt.text(i+1,degree[i],'{}'.format(round(degree[i], 2)), ha='left', va = 'bottom', ma='center')

plt.axhline(np.mean(temp), color='red', linestyle="--", label='Mean of 9 Years')
plt.text(1,degree[3],'{}'.format(round(degree[3], 2)), ha='left', va = 'bottom', ma='center')

plt.legend(loc = 'upper right')

ax=plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))

plt.ylim(16,32)
plt.xlabel('Month')
plt.ylabel('Temperature in Degree C')
plt.title('Tainan Monthly Mean Temperature Of 2013 To 2021')

# L13_3
fig = plt.figure(figsize=(15,6))
plt.subplot(1,2,1) # 第一張圖
for i in range(0,9):
    plt.plot(list(range(1,13)),temp_list[i],label=str(int(year[i])))
    plt.legend(loc = 'lower center')

ax=plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))

plt.xlabel('Month')
plt.ylabel('Temperature in Degree C')
plt.title('Tainan Monthly Mean Temperature From 2013 To 2021')

plt.subplot(1,2,2) # 第二張圖
plt.plot(list(range(1,13)),degree) #, marker='o',  markerfacecolor='r', markersize=5
plt.scatter(list(range(1,13)),degree, c='red', alpha=1)
for i in range(12):
    plt.text(i+1,degree[i],'{}'.format(round(degree[i], 2)), ha='left', va = 'bottom', ma='center')

plt.axhline(np.mean(temp), color='red', linestyle="--", label='Mean of 9 Years')
plt.text(1,degree[3],'{}'.format(round(degree[3], 2)), ha='left', va = 'bottom', ma='center')

plt.legend(loc = 'upper right')

ax=plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))

plt.ylim(16,32)
plt.xlabel('Month')
plt.ylabel('Temperature in Degree C')
plt.title('Tainan Monthly Mean Temperature Of 2013 To 2021')

plt.tight_layout()
plt.show()
fig.savefig('lab13_3.png')

```

### Lab13 加分題 參考答案
```python=
#read file
x = []
y = []
path = 'oddExperiment.txt'
with open(path) as f:
    next(f)
    for line in f.readlines():
        s = line.split(' ')
        x.append(float(s[0]))
        y.append(int(s[1]))

print(x)
print(y)
# print(score)

# 定義誤差函數
def error(x, y, degree):
    results = {}
    coeffs = np.polyfit(x, y, degree)
    p = np.poly1d(coeffs)
    #calculate r-squared
    yhat = p(x)
    ybar = np.sum(y)/len(y)
    ssreg = np.sum((yhat-ybar)**2)
    sstot = np.sum((y - ybar)**2)
    # results['R2'] = ssreg / sstot
    
    results['R2'] = r2_score(y,yhat)


    #calculate MSE
    mse = np.mean((y - yhat)**2) 
    # results['MSE'] = mse
    results['MSE'] = mean_squared_error(y, yhat)

    return results

model1 = np.poly1d(np.polyfit(y, x, 1))
model2 = np.poly1d(np.polyfit(y, x, 2))
polyline = np.linspace(10, -10, 20)
plt.scatter(y, x, label='Data')
plt.plot(polyline, model1(polyline), label='Fit of degree 1, LSE = '+ str(round(error(y, x, 1)['MSE'], 5)), c='orange')
plt.plot(polyline, model2(polyline), label='Fit of degree 2, LSE = '+ str(round(error(y, x, 2)['MSE'], 5)), c='g')
plt.plot(polyline, model1(polyline), label='Fit of degree 1, R2 = '+ str(round(error(y, x, 1)['R2'], 5)), c='r')
plt.plot(polyline, model2(polyline), label='Fit of degree 2, R2 = '+ str(round(error(y, x, 2)['R2'], 5)), c='purple')
plt.title('oddExperiment Data')
plt.legend(loc = 'upper center')
plt.show()
``` -->

- 一個沒對其 -10