---
# System prepended metadata

title: 智慧數據研究所 Python寒假自學班

---

# 智慧數據研究所 Python寒假自學班
特別感謝黃登揚老師、王斯弘老師分別提供教學影片和講義等資源<br>
以及吳晉東教授、薛雅馨所長提供獎助學金給兩位助教
![](https://i.imgur.com/j5o5sl4.jpg)

## Warm Up
### [Anaconda 基本安裝](https://docs.google.com/presentation/d/1YMmrnzn-0RQOLwQFFbCB6AsmL7yQ44jK/edit?usp=sharing&ouid=102852266542138890855&rtpof=true&sd=true)
* [官方網站(下載位置)](https://www.anaconda.com/products/distribution)
* Anaconda打包了資料科學常用的套件，並提供虛擬環境管理等豐富的功能
* 推薦初學者使用編輯器 : Spyder 或者 Jupyter Notebook
* 進階使用編輯器 : Visual Studio Code
* [利用 conda 建立及管理 Python 虛擬環境 (2023更新版)](https://simplelearn.tw/2022/08/11/用-conda-建立及管理-python-虛擬環境-2022更新版/)
* [Python初學 — jupyter 介紹](https://sean22492249.medium.com/skiwitch-talk-code-creates-the-world-2-f848557997e6)

### [Colab基本教學](https://docs.google.com/presentation/d/1YMmrnzn-0RQOLwQFFbCB6AsmL7yQ44jK/edit?usp=share_link&ouid=102852266542138890855&rtpof=true&sd=true)
* [Google Colab](http://colab.research.google.com)
* 類似線上版的Jupyter Notebook
* 免費版有一天12小時的使用限制
* 付費版(Colab Pro)有提供更好的GPU和使用時間(每月9.99美金/49.99美金)
* 學校有提供**免費**的AI運算資源(AI-Stack)，介面採用比Jupyter Notebook更進階的[JupyterLab](https://jupyterlab.readthedocs.io/en/stable/)，且模型訓練速度比Colab快很多
    * 限在校園內使用（使用學校網路）
    * 需由任課老師或指導教授申請
    * [說明](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjm3ZebrsP8AhXV0mEKHZ5FB5AQFnoECA0QAQ&url=https%3A%2F%2Fwww.yuntech.edu.tw%2Findex.php%2F2019-07-25-11-32-12%2F2019-04-10-08-05-51%2F2019-03-18-07-24-53%2Fitem%2Fdownload%2F3046_d3beb063b85687359cc7df5719d20ac7&usg=AOvVaw2XRK1kjqhp1N4UqebUijB6)

### 補充
---
#### Miniconda : Anaconda的瘦身版
Anaconda因為打包了大多數的資料科學套件，因此安裝檔案非常龐大，但也因此可以省掉繁瑣的安裝過程和環境配置，然而我們可能不需要用到所有的套件，也可能沒有**足夠的硬碟空間**，因此有miniconda的出現，僅僅保留環境控制等功能，套件部分需自行手動安裝，讓電腦空間不浪費。

因為有非常多需要手動操作的設定，推薦等熟悉Anaconda的操作和環境後，且知道自己跑的程式碼可能需要用到哪些套件以及Python版本時，再考慮移除Anaconda，安裝miniconda。
* [Miniconda官方文件](https://docs.conda.io/en/latest/miniconda.html)
## Week 1 (1/16 ~ 1/20)
### [Python在產業的應用現況介紹](https://drive.google.com/file/d/1wiNb76GKTXy40IYs9HytvW_G3ZzqKmbF/view?usp=sharing)
![](https://i.imgur.com/6MYvfeZ.jpg)
* 認識Python的歷史及現況
* 介紹Python的實作延伸
* 介紹Python的基本安裝(*這部分如果已經安裝過Anaconda，可以不用再安裝，Anaconda本身就已經包含了Python的安裝了。*)
:::success
:bulb: 實作

首次接觸Python，希望在安裝的過程沒遇到什麼困難，接著讓我們一起來嘗試操作Python。

* 打開命令提示字元，輸入`python -V`的指令，來查看目前的Python版本。
* 接續上述的操作介面，透過`python -c "import this"`，來查看Python的設計精神。

:::

### [Python開發環境介紹、資料型態介紹](https://drive.google.com/file/d/1PL61P6dkWLX_n23UaXXkgHiRUFW6BpzC/view?usp=share_link)
* 介紹如何使用REPL(Read-Eval-Print-Loop)，又稱為Python Shell
* 編碼問題：最好使用UTF-8編碼（預設即可）
* 在Python Code中，```#```開頭的那一行爲註解（Comment）
* 載入模組的介紹
    ```python
    import numpy           #單純載入模組
    import numpy as np     #將numpy取名為np (簡稱)
    from numpy import random #從numpy模組裡載入random這個函數
    ```
* Python常用的IDE介紹（*Anaconda裡面已經包含了Spyder*）
* 資料型態
    * 可用```type()```來知道變數是哪種資料型態
    * ```int``` ：整數 (0,1,2,3,4,5,6 ...)
    * ```float``` : 浮點數（後面有小數點的像是1.53, 2.89, 3.14 ...）
    * ```bool``` : 布林型態(只有```True```跟```False```兩種可能，或者說```1```跟```0```的兩種可能)
    * ```""```, ```''```,```str```: 字串（也就是文字，像是```"Hello word!"```, ```"Number 4"```...）
        * 字串輸出(```print```)的格式化
        ```python
        #以下皆會輸出 I have 10 apples.
        #方式一（新版）
        print("I have {} {}.".format("10","apples"))
        #方式二 (舊版)
        print("I have %s %s." % ("10","apples"))
        ```
    * ```list``` : 串列（清單)
        * 有順序之分
        * 元素可以重複
        ```python
        #建立一個list
        numbers = [1,2,3,4,5,6,7,8,9] 

        #新增一個元素
        numbers.append(10)

        #刪除一個元素
        numbers.remove(8) # 移除numbers裡面找到第一個值為8的元素
        del numbers[0] #移除numbers裡面索引值(index)為0的元素（值為1）

        #使用in、not in運算子檢查是否存在
        4 in numbers #回傳True
        20 in numers #回傳False
        32 not in numbers #回傳True
        ```
        >可參考[Python串列(list) 基礎與23個常用操作](https://selflearningsuccess.com/python-list/)
    * ```set``` : 集合
        * 沒有順序之分
        * 元素不能重複
        ```python
        #set的表示方式    
        users = {"William","Mackenzie"} 

        #新增元素到users中
        users.add("Chiu")

        #刪除users中值為"William"的元素
        users.remove("William") 
        ```
    * ```dict``` : 字典
        * 兩兩對應的鍵(key)和值(value) 
        * dict中，鍵(key)不能重複，僅能有一個存在(Hashable)
        ```python
        #建立字典
        users_password = {"William":12345, "Mackenzie":45678}

        #取得鍵為"william"之值
        users_password["William"]

        #items(), keys(), values()用法

        #回傳[("William",12345),("Mackenzie",45678)]
        list(users_password.items())

        #回傳["William","Mackenzie"]
        list(users_password.keys())

        #回傳[12345,45678]
        list(users_password.values()) 
        ```
    * ```tuple``` : 元組
        * 與```list```類似，差別在於一但建立後不能再變更裡面的值
        ```python
        #宣告Tuple
        users = ("William","Mackenzie")

        #取值(與list一樣)
        users[0] #回傳William
        ```
![](https://i.imgur.com/9KmGSdQ.jpg)

:::info
:bulb: Q&A
* 請問在Python程式中，單行註解的符號是什麼？
* 在撰寫Python程式時，若想引用其他套件的資源，可以透過哪個指令協助？
* 若想知道某個資料的型態，可以用哪個函式協助查詢？
* 在Python中哪個資料的結構是無序，而元素是不重複的呢？
* 在Python中哪個資料的結構，是儲存鍵與值對應的呢？
:::
:::success
:bulb: 實作

經過這週的課程，我們可以用Python來小試身手，讓我們一起來試著解決下列的問題。

1. 建立一個程式，以"學號_Q1.py"進行命名，提供使用者輸入三次字串資料，列出三次輸入資料中不重複的字串與數量。例如以下的執行結果：
```
>python 學號_Q1.py
請輸入第1個字串：abc
請輸入第2個字串：abc
請輸入第3個字串：def
有 2 個不重複字串： {'def', 'abc'}
```
*註: `>python 學號_Q1.py` 是指在命令提示元輸入該指令*

2. 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入三次字串資料，列出輸入的所有字串。並提供一次查詢的輸入，來觀察資料是否曾經輸入。例如以下的執行結果：
```
>python 學號_Q2.py
請輸入第1個字串：abc
請輸入第2個字串：abc
請輸入第3個字串：def
請輸入查詢字串：abc
abc 存在 ['abc', 'abc', 'def'] 資料中： True
```
:::
:::warning
:dagger_knife: 挑戰

Q&A
* 請試著說明以下a,b,c,d四種變數的資料型態差別
```python
a=11
b="11"
c=11.0
d=[11]
```
* ```dict```的key與```list```的index中資料型態的比較
```python
#numbers是一個list，裡面總共包含了2個1，4個3，5個1
numbers = [1,1,3,3,3,3,5,5,5,5,5,5]
#dict_numbers的key為numbers裡的數字(資料型態為字串)，value為numbers裡數字的個數
dict_numbers = {"1":2,"3":4,"5":6}

#(1)請問假設我要從numbers取第2個值為3的元素,
#我要用
numbers["3"]
#還是
numbers[3]

#(2)請問假設我要從dict_numbers取數字3的個數,
#我要用
dict_number["3"]
#還是
dict_number[3]
```

:::
### [說明Python程式運算子](https://drive.google.com/file/d/1MfTu2hXG8ZJnPahNKED_jQ8_LXpQmbbt/view?usp=sharing)
* ```decimal```套件可以處理小數點後的精度問題(Numpy也行)
* 刪除變數：使用```del```
* ```+```,```-```,```*```,```/``` : 分別為加減乘除
* ```%```：為取餘數
* ```//```：為整除(取商)
* ```**```：為指數運算
* ```>=```,```<=```,```==```,```!=```,```>```,```<```:分別為大於等於、小於等於、等於、不等於、大於、小於
* ```and```, ```or```：邏輯運算子（且、或）
    ```python
    a = 4
    b = 5
    a+b #return 9
    a-b #return -1
    a*b #return 20
    a/b #reutrn 0.8
    a%b #return 4
    a//b #return 0
    a>=b #return False
    a<=b #return True
    a==b #reutrn False
    a!=b #return True
    a>b #reutrn False
    a<b #return True

    a<=b and a!=b #return True
    a>b  or a==b #return False
    ```
* 索引切片：使用```[start:end:step]```
    ```python
    a = [1,2,3,4,5,6,7]
    a[1:-2:2] #return [2,4]
    ```
:::info
:bulb: Q&A
* 請問在Python程式中，想解決浮點數不精確的問題，可以透過哪個套件來協助？
* 在撰寫Python程式時，若想刪除變數，可以透過哪個指令協助？
* 若想獲得整除的結果，可以用哪個運算子？
* 在Python中'Hello'的字串str物件，若進行索引切片的運算，str[:2]會得到什麼結果呢？
* 在Python中，若想進行邏輯的運算，要如何得到"而且"的結果？
:::

:::success
:bulb: 實作

運算子的善用能協助Python解決數值操作，讓我們一起來處理下列的需求。

1. 建立一個程式，以"學號_Q1.py"進行命名，提供使用者輸入三次數字資料，列出三次輸入的加總結果。例如以下的執行結果：
```
>python 學號_Q1.py
請輸入第1個數字：0.1
請輸入第2個數字：0.1
請輸入第3個數字：0.1
加總結果： 0.3
```
2. 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入二次字串資料，列出輸入的字串相加的結果。並提供一次索引切片數值的輸入，來進行資料的分割，分別判斷是否為小寫的資料。例如以下的執行結果：
```
>python 學號_Q2.py
請輸入第1個字串：abc
請輸入第2個字串：Def
字串相加結果： abcDef
請輸入索引切片值：3
第1個字串是小寫： True
第2個字串是小寫： False
```
:::

:::warning
:dagger_knife: 挑戰

Q&A
* 請試著不要直接用程式去跑，自行判斷以下值兩個print()會印出True還是False
```python
a,b,c,d = 42,29,90,13
print((a > b or c < d) and (d < a or c > b))
print((b+d > a and c-a+a*b > b+c*d) or (a%b > d and (b*c)%9+d < a+c))
```
:::
### 補充
---
#### ```sys.argv```
當你從命令列呼叫Python程式時，可以在後面增加多個參數，並由```sys.argv```來讀取該內容，這樣的方法我們稱為**命令列引數**（command-line argument)。這是作為程式從外部獲取參數的橋樑之一，並且可以傳遞多個參數，因此```sys.argv```的值預設是個```list```，其中第0個值```sys.argv[0]```為所執行python程式的路徑，之後才是使用者自行加入的值。

首先建立一個test.py檔，程式碼如下：
```python
import sys
print(sys.argv[0])
print(sys.argv[1])
print(sys.argv[2])
```
然後開啟命令提示元或者終端機執行：
```shell
$ python test.py abc 123
(輸出結果)
test.py
abc
123
```
```sys.argv[0]```為我們的檔案路徑和名稱，而abc,123會分別被存入```sys.argv[1]```，```sys.argv[2]```中。你也可以直接呼叫```sys.argv```取得整個list。

**值得注意的是當你沒有額外輸入任何引數，卻想讀取```sys.argv[1]```或者```sys.argv[2]```，會出現索引錯誤，找不到其值。**
> [Python sys.argv 用法](https://shengyu7697.github.io/python-sys-argv/)

#### ````argparse````
>然而，```sys.argv```只能將程式引數一個個以陽春的陣列傳遞，當你需要解析更複雜的引數，又能更有彈性且有序的整理其引數，這時候就會推薦使用```argparse```!<br>[Python argparse 教學：比 sys.argv 更好用，讓命令列引數整潔又有序](https://haosquare.com/python-argparse/)
## Week 2 (1/30 ~ 2/3)
### [Python流程語法](https://drive.google.com/file/d/1Wsuco0D2vOEekdKwkGWU53kUB6Lm5y2e/view?usp=share_link)
* 判斷語法
```python
a = 20 #假設

#單層判斷句
if a == 20:
    #......

#雙層判斷句
if a == 10:
    #......
else:
    #......

#三層以上判斷句（可無限多層）
if a == 30:
    #......
elif a == 20:
    #......
elif a == 10:
    #......
else:
    #......
```
* 迴圈(loop)
```python
a = 20
while a<100: #判斷條件
    pirnt(a)
    a+=1 #要讓a值發生變化，以免進入無限迴圈（會當機）

for i in range(a,100): 
    #range(初始值,最後的值+1) -> range(1,100)會從1跑到99
    #range(最後值+1) -> range(100) 會從0跑到99
    print(a)

#以上兩個迴圈寫法相等

for i,j in zip([0,1,2],["A","B","C"]):
    #同時迭代多個 list
    #每次分別從各個 list 中取一個元素配成同一組，
    #一組一組整齊對應
    #迴圈的輸出分別為：(0,"A"),(1,"B"),(2,"C")
    print(i,j)

for i,j in enumerate(["A","B","C"]):
    #將每個元素的前面加上編號(從0開始)
    #迴圈的輸出分別為：(0,"A"),(1,"B"),(2,"C")
    print(i,j)
#以上兩個迴圈寫法相等
```
>* [Python 函式 zip() 教學：同時迭代多個 list，學習刷題與資料分析技巧](https://haosquare.com/python-zip-function/)
>* [[Python] 使用 enumerate() 函式來同時輸出索引與元素](https://clay-atlas.com/blog/2019/11/08/python-chinese-function-enumerate/)
* List Comprehension(列表推導式)
```python!
a = [i for i in range(100)]
#等同於
a = []
for i in range(100):
    a.append(i)


fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
newlist = [x for x in fruits if "a" in x]
#等同於
newlist=[]
for x in fruits:
    if "a" in x:
        newlist.append(x)
```
>[Python - List Comprehension](https://www.w3schools.com/python/python_lists_comprehension.asp)
:::info
:bulb: Q&A
* 請問在Python程式中，協助做選擇的結構是哪個名稱的程式區塊？
* 在撰寫Python程式時，搭配bool型態進行控制的迴圈，是哪個名稱的程式區塊？
* 若想取得迭代的內容指，可以用哪個名稱的程式區塊？
* 在Python中協助迭代結構增加索引的函數名稱為？
* 在Python中，若執行print(list(range(1,4)))，會得到什麼結果？
:::
:::success
:bulb: 實作

學習完流程控制的應用，能讓我們操作更多的Python執行過程，讓我們一起來處理下列的需求。

* 建立一個程式，以"學號_Q1.py"進行命名。設計一猜數字的遊戲，首先先產生出一個謎底數字，裡面存放隨機從1到10之間的數字。設計一迴圈，讓使用者可以反覆猜測數字，若猜測的答案還不是謎底數字時，則迴圈持續執行。如果猜測的數字比謎底大，則顯示"請猜小一點"，如果猜測的數字比謎底小，則顯示"請猜大一點"，如果猜測的數字與謎底相同，則顯示"恭喜您猜中了"。例如以下的執行結果：
```
>python 學號_Q1.py
請猜謎底數字是：8
請猜小一點
請猜謎底數字是：6
請猜大一點
請猜謎底數字是：7
恭喜您猜中了
```

* 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入姓名，利用enumerate函數協助及索引切片運算的幫忙，透過迴圈逐一列出逆排的使用者姓名字母及索引，索引必須從1開始註記。例如以下的執行結果：
```
>python 學號_Q2.py
請輸入您的名字：Yuntech
7 h
6 c
5 e
4 t
3 n
2 u
1 Y
```
:::
:::warning
:dagger_knife: 挑戰

考完期末考後，老師想要發放期末考考卷，並把名字和對應到的成績分別存在```names```和```scores```中，
請試著使用一層```for```迴圈，並使用```zip()```和```enumerate()```印出發考卷的順序、姓名、分數。
```python
names = ["Mackzine","Grace","William","Chiu","Cindy",
         "Arron","Tina","Karl","Clara"]
scores = [71,92,87,85,69,68,84,90,89]

# 預期輸出：
# 第1個拿考卷的是Mackzine,分數:71
# 第2個拿考卷的是Grace   ,分數:92
# 第3個拿考卷的是William ,分數:87
# 第4個拿考卷的是Chiu    ,分數:85
# 第5個拿考卷的是Cindy   ,分數:69
# 第6個拿考卷的是Arron   ,分數:68
# 第7個拿考卷的是Tina    ,分數:84
# 第8個拿考卷的是Karl    ,分數:90
# 第9個拿考卷的是Clara   ,分數:89
```



:::
![](https://i.imgur.com/hRCU3l5.jpg)

### [Python函式設計](https://drive.google.com/file/d/17-jQ5jQzlesSXXi6yzG8B4Bq5jw7uWNl/view?usp=sharing)

>在寫程式碼時有一個非常重要的觀念是DRY(Don’t Repeat Yourself)，意思是避免同樣的程式碼重複出現在很多個地方，除了可讀性很低外，也不易維護。所以要適當的進行封裝，來達到程式碼的重用性(Reusable)。<br>
[[Python教學]5個必知的Python Function觀念整理](https://www.learncodewithmike.com/2019/12/python-function.html)
```python
#取得arr的平均
numbers = [5,6,7,8,9,1,2,3,4]
def average(arr):
    return sum(arr)/len(arr) #arr的總和sum()/arr的個數len()
print(average(numbers))
```
* ```global```以及```nonlocal```
>[[Python]自學 Python 100 天，全域變數、區域變數(global、nonlocal)](https://ktinglee.github.io/LearningPython100days(6)_global_and_nonlocal/)
```python
x = 100
def change_x():
    global x
    x = 10
change_x()
print(x) #加入global x時,x值才會變動

def function1():
    y = 100
    def function2():
        nonlocal y
        y = 200
    function2()
    print(y)
function1() #加入nonlocal時，y值才會變動
```
* list的排序
```python
numbers = [5,6,7,8,9,1,2,3,4]
#回傳新的list
sorted(numbers) #return [1,2,3,4,5,6,7,8,9]
sorted(numbers, reverse=True) #return [9,8,7,6,5,4,3,2,1]

#對原本的list進行排序
numbers.sort()
numbers.sort(reverse=True)
```



:::info
:bulb: Q&A
* 請問在Python程式中，若要設計函式得使用哪個名稱的關鍵字來進行？
* 在撰寫程式時，若設計了函式呼叫自身的作法，這做法稱之為何？
* 在設計函式的過程中，若要提供不定數目的參數時，可以用哪個符號加註在前來提供功能？
* 在Python中協助查詢區域變數名稱與值的函數名稱為？
* 在Python中，若希望針對全域範圍的變數進行指定時，可用使用哪個關鍵字來協助宣告？
:::
:::success
:bulb: 實作

學習完函式的設計應用，能讓我們能重用這些設計好的Python程式來加速開發過程，接續讓我們一起來練習處理下列的需求。

* 建立一個程式，以"學號_Q1.py"進行命名。設計一計算長方形面積及周長的程式，首先設計一函式，能接受兩個參數，透過參數計算出長方形面積。再設計一函式，能接受兩個參數，透過參數計算出長方形周長。並提供使用者輸入長跟寬，輸出面積的結果。例如以下的執行結果：
```
>python 學號_Q1.py
請輸入長方形邊長：8
請輸入長方形邊寬：6
長方形面積： 48
長方形周長： 28
```


* 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入身高(公分)及體重(公斤)，利用函式的設計進行BMI的計算(公斤/公尺平方)，透過範圍的判斷來給予提醒，在18.5以下(不包含)者為"體重過輕"，在24以上(包含)者為"體重過重"，在18.5與24區間者為"正常範圍"。例如以下的執行結果：
```
>python 學號_Q2.py
請輸入您的身高(公分)：160
請輸入您的體重(公斤)：70
體重過重，BMI： 27.343749999999996

>python 學號_Q2.py
請輸入您的身高(公分)：170
請輸入您的體重(公斤)：60
正常範圍，BMI： 20.761245674740486

>python 學號_Q2.py
請輸入您的身高(公分)：180
請輸入您的體重(公斤)：50
體重過輕，BMI： 15.432098765432098
```
:::
:::warning
:dagger_knife: 挑戰

我們知道神經網路常見的激勵函數(Activation Function)有sigmoid,softmax等。
而sigmoid function公式如下：
>$$sigmoid(x)=\frac{1}{1+e^{-x}}$$

而softmax則是：

>$$softmax(x_{i})=\frac{e^{x_{i}}}{\sum_{j=1}^{n}{e^{x_{j}}}}$$

請試著僅使用```numpy```中的[```numpy.exp()```](https://numpy.org/doc/stable/reference/generated/numpy.exp.html)和內建函式[```sum()```](https://www.w3schools.com/python/ref_func_sum.asp)，輸入一個串列，來實作兩個函數，並輸出其值:
```python
import numpy as np
input = [1,3,5,7,9]
def sigmoid(x):
    #請完成code

def softmax(x):
    #請完成code

print(f"sigmoid:{sigmoid(input)},softmax:{softmax(input)}")
```
:::
![](https://i.imgur.com/1igZZig.jpg)

### 補充
---
#### list的key技巧
>Both list.sort() and sorted() have a key parameter to specify a function (or other callable) to be called on each list element prior to making comparisons.<br>[Sorting HOW TO¶](https://docs.python.org/3/howto/sorting.html)

當我們想要處理一維資料時，我們可以簡單地使用```.sort()```或者```sorted()```，然而，有時候我們需要處理的不是一筆資料，而是**一組**資料，
以下我們舉出一個最常見的學生成績排序，假設有五位學生分別Grace,Cindy,Mackzine,William,Chiu，而他們的座號(1~5)和成績如下(沒有按照任何順序):
```python
scores = [
    ["Mackzine",3,99],
    ["Chiu",5,87],
    ["William",4,90],
    ["Cindy",2,69],
    ["Grace",1,88]
]
```

我們希望這筆資料可以有三種排序方式，分別是按照姓名排序、按照座號排序、按照成績排序，請問可以怎麼做呢？
這時候就可```sorted()```和```.sort()```中的參數參數```key```，並且搭配```lambda```函式。
>```lambda```的功能就像是使用def的方式一樣，只是寫法上更為簡潔，可以寫在行內，在使用前不需要先把函式綁定在一個特定的名稱上。<br>
>簡易範例:
>```python
>def square(
>    return x ** 2 #求某個數的平方
>#如果改用lambda函式來撰寫的話，會以下面的方式呈現：
>square = lambda x: x**2
>```
>[Python- lambda 函式](https://medium.com/seaniap/python-lambda-函式-7e86a56f1996)

```python
#按照姓名排序(英文字母)
scores.sort(key=lambda x: x[0])
sorted(scores,key=lambda x:x[0])
"""
Result :
[['Chiu', 5, 87],
['Cindy', 2, 69],
['Grace', 1, 88], 
['Mackzine', 3, 99], 
['William', 4, 90]]
"""
#按照座號排序
scores.sort(key=lambda x: x[1])
sorted(scores,key=lambda x:x[1])
"""
Result:
[['Grace', 1, 88],
['Cindy', 2, 69],
['Mackzine', 3, 99],
['William', 4, 90],
['Chiu', 5, 87]]
"""

#按照成績排序
scores.sort(key=lambda x: x[2])
sorted(scores,key=lambda x:x[2])
"""
Result:
[['Cindy', 2, 69],
['Chiu', 5, 87],
['Grace', 1, 88],
['William', 4, 90],
['Mackzine', 3, 99]]
"""
```
>```key=lambda x: x[2]```指命令scores這個list中，最外層的每個元素叫做x，然後將每個x指定一個比較值，這個值來自於自己那個x裡面```index=2```的這一項作為比較標準。例如：```["Mackzine",3,99]```的key就是被指定99，```["Cindy",2,69]```的key就是被指定為69。<br>[[Day21]排序？index sort? lambda又有你的事了？](https://ithelp.ithome.com.tw/articles/10218710)

如果我們需要的不是排序後的結果，而是排序後，原本list的**index**，換句話說就是當我要這個排序好的值時，我要從原本的那個list哪個index抓？
```python
scores = [
    ["Mackzine",3,99],
    ["Chiu",5,87],
    ["William",4,90],
    ["Cindy",2,69],
    ["Grace",1,88]
]
#按照成績排序
sorted(range(len(scores)),key=lambda x:scores[x][2])
# Result : [3, 1, 4, 2, 0]
```
>透過range(len(scores))來建立scores list的index，依序為0,1,2,3,4。因此，真正被操作sorting的是index，而非scores list本身，同時利用key來幫忙，利用lambda指定每個index的value。<br><br>
>將scores裡的每一筆資料依序指定給0, 1, 2, 3, 4，即scores[x]，而在sorting時就是利用scores[x][2]的數值大小進行排列。例如，index=0是被指定數值為99，index=3是被指定數值為69，排序時就是看數值99,87,90,69,88進行index的排序，也就是用成績排進行排名。
><br>[[Day21]排序？index sort? lambda又有你的事了？](https://ithelp.ithome.com.tw/articles/10218710)

最後，如果我們同時需要排序後結果以及原本的list的**index**，我們可以使用```enumerate```函式：
```python
scores = [
    ["Mackzine",3,99],
    ["Chiu",5,87],
    ["William",4,90],
    ["Cindy",2,69],
    ["Grace",1,88]
]
#按照成績排序，index被往後推(+1)，前面多了一個值(這個list本身的index)
#加入enumerate，會變成(0,["Mackzine",3,99]),(1,["Chiu",5,87])...以此類推
#因此想要取99這個值要用x[1][2]
sorted_scores=sorted(enumerate(scores),key=lambda x:x[1][2])
print("按照成績排序後的結果和原本的index")
for index,data in sorted_scores:
    print(f"原本的index={index}:{data}")

'''
按照成績排序後的結果和原本的index
原本的index=3:['Cindy', 2, 69]
原本的index=1:['Chiu', 5, 87]
原本的index=4:['Grace', 1, 88]
原本的index=2:['William', 4, 90]
原本的index=0:['Mackzine', 3, 99]
'''
```

#### map(),filter()用法
>map()和filter()都是能將函數當做參數的高階函數

```map()```最大的好處在於大幅減少繁雜的程式碼，其用途在於對一個list的每個元素做處理，可以搭配```lambda```來更簡潔，另外注意的是其回傳是一個map物件，記得透過list()來轉換成來轉換成list。
```python
map(function, iterator)
#function:函式 
#iterator:迭代器（像是list,eumerate(),range()等）
```

今天老師發現有些同學成績不及格(未滿未滿70分)，因此想要做調分，讓分數不要那麼難看，將分數開根號乘以10再四捨五入：
```python
    #依座號排序(1號~13號)
scores = [
    70,49,56,34,56,79,12,56,62,87,30,73,47
]
new_scores=list(map(lambda x:round(x**0.5*10),scores)) #調分：開根號乘以乘以10再四捨五入
print(new_scores)
'''
[84, 70, 75, 58, 75, 89, 35, 75, 79, 93, 55, 85, 69]
'''
```
```filter```也是為了減少繁雜的程式碼，其用途在於對於一個list尋找是否有符合條件的元素（有點過濾的概念），一樣可以搭配```lambda```，另外注意的是其回傳是一個filter物件，記得透過list()來轉換成來轉換成list。
```python
filter(function, iterator)
#function:函式 
#iterator:迭代器（像是list,eumerate(),range()等）
```

調完分之後的分數存在```new_scores```裡面，老師想知道即使調分後還是有誰不及格，分數又是多少？
```python
#小於70為不及格，使用enumerate()則是為了加上座號
failed_scores = list(filter(lambda x:x[1]<70,enumerate(new_scores))) 
print("不及格名單：")
for index,score in failed_scores:
    print(f"座號{index:>2}:{score}")
'''
不及格名單：
座號 4:58
座號 7:35
座號11:55
座號13:69
'''
```
>* [[Python] 內建函式filter, map, reduce](https://dotblogs.com.tw/law1009/2013/07/09/109217)
>* [Day14- Python 高階函數map, filter, reduce 介紹](https://ithelp.ithome.com.tw/articles/10216479) 
>* [filter() in python](https://www.geeksforgeeks.org/filter-in-python/)
>* [Python map() function](https://www.geeksforgeeks.org/python-map-function/)

#### Type Annotation
>Type annotations - also known as type signatures - are used to indicate the datatypes of variables and input/outputs of functions and methods.

如果你學過C/C++,Java等，在宣告變數時，你會發現你必須宣告這是什麼型別(Type)，而在Python是不需要的。

讓我們看一下C++與Python在宣告字串上的差別:
```cpp
/* 這是C++的程式碼 */
#include <iostream>
using namespace std;
int main(){
    char* hello="hello world!"; /* C++必須宣告他是一個字串(字元陣列) */
    cout<<hello<<endl;
}
```
```python
#這是python的程式碼
hello = "hello world!" #python不需要宣告
print(hello)
```

一般來說我們會將程式語言區分成動態語言(Dynamically Typed Languages)和靜態語言(Statically Typed Languages)。而Python則是屬於**動態語言**，在程式撰寫時不用明確的型別宣告。
> 了解更多：[你不可不知的 JavaScript 二三事#Day2：資料型態的夢魘——動態型別加弱型別(1)](https://ithelp.ithome.com.tw/articles/10201839)
> <br>**推薦分清楚動態/靜態語言，強型別/弱型別的差異**

然而，在Python也可以做到這種註釋型別的要求，就是使用**Type Hints**，Type Hints 是透過Type Annotation讓程式碼能表達更明確、更易閱讀，同時也能提升開發效率。
```python
def happy(name:str,score:int) -> str: 
    #name進去應該要是str(字串)
    #score進去應該要是整數
    #回傳應該要是str(字串)
    score = round(score**0.5*10)
    return f"{name},你的成績是{score}"
```
也就是說這份程式碼很明確的告訴你，```name```應該是字串，```score```也告訴你應該是**整數**(不是浮點數)~~（老師就是不想給你小數點後的分數啦）~~，而輸出應該是字串。在程式碼非常龐大的時候，可以讓你在很短的時間內判斷這個函式的輸入型別。

為何我用**應該**呢？因為這仍不能解決型別誤用的情況，這僅僅是**註釋**(annotation)而已，無法偵測誤用/錯用型別的情況。更積極的做法是透過型別檢查器(type checker)直接找出錯誤，例如來自Facebook的[mypy](https://github.com/python/mypy)。

可以透過```pip install mypy```來安裝，然後輸入:
```shell
$ mypy test.py(你的py檔)
```
但你可能不想每次都要一直輸入```mypy```指令，可以使用Visual Studio Code中延伸模組的Mypy套件，每次執行時，就會自動告知你的input型別不一致。
![](https://i.imgur.com/B6n7tD2.png)

![](https://i.imgur.com/pjlfx4c.png)

![](https://i.imgur.com/cQnlIBr.png)

>* [使用 Python typing 模組對你的同事好一點
](https://myapollo.com.tw/zh-tw/python-typing-module/)
>* [Python Type Hints 教學：我犯過的 3 個菜鳥錯誤](https://haosquare.com/python-type-hints-3-beginner-mistakes/)

## Week 3 (2/6 ~ 2/10)
### [常用內建模組](https://drive.google.com/file/d/1ooRajvDTBEnLMx7pSkiUqZNnewwdx2HG/view?usp=sharing)
* time模組 - localtime()、strptime()、strftime()、time.sleep()
    * localtime()-可提供目前所在時間
    ```python
    import time
    print(time.localtime())#提供目前所在時間
    >>> time.struct_time(tm_year=2023, tm_mon=2, tm_mday=5, tm_hour=13, tm_min=34, tm_sec=57, tm_wday=6, tm_yday=36, tm_isdst=0)
    ```
    * strptime()-有個代表時間的字串，想要將其剖析為 struct_time
    ```python
    import time
    print(time.strptime("2018-05-26", '%Y-%m-%d'))#對照格時如下表
    >>> time.struct_time(tm_year=2018, tm_mon=5, tm_mday=26, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=146, tm_isdst=-1)
    ```
* 時間格式全部都是使用一個%，加上一個字母來代表，其中大小寫會有不同的意義，這裡舉一寫比較常使用到的引述作為舉例。
    * strftime()- 接受一個格式指定與 struct_time 實例
    ```python
    import time
    d = time.strptime("2018-05-26", '%Y-%m-%d') #原本的年-月-日格式
    print(time.strftime('%d-%m-%Y',d))#轉換為自己想要的 日-月-年格式
    >>> 26-05-2018
    ```
    * time.sleep()-用來做延遲的功能
    ```python
    time.sleep(5)
    print("You wait 5 secs.")
    >>> 5秒後印出 You wait 5 secs.
    ```
* datetime模組 - datatime.date、datatime.time、datetime.datetime
    * datatime.date - 取得今天的日期
    ```python
    date_today = datetime.date.today()
    print(date_today)
    >>> 2023-02-05
    ```
    * datatime.time
    ```python
    max = datetime.date.max # 查看date的最大值
    min = datetime.date.min # 查看date的最小值
    print(max)
    print(min)
    >>> 9999-12-31
    >>> 0001-01-01
    ```
    * datatime.datetime
    ```python
    max = datetime.time.max # 查看time的最大值
    min = datetime.time.min # 查看time的最小值
    print(max)
    print(min)
    >>> 23:59:59.999999
    >>> 00:00:00
    ```
:::info
:bulb:Q&A
* 請問Unix中，UTC的時間起始是哪個時間？
* 在Python裡，datatime模組中有哪些類別來定義表示人類時間的概念？
* 在Python操作過程中，如果要讓datatime模組中時間使用ISO8601標準來顯示，需要透過哪一個方法來協助？
* Python中若要進行日誌的記錄，可以透過哪個模組來協助？
* 在Python中日誌記錄分為哪幾種層級？
:::

:::success
:bulb:實作
* 建立一個程式，以"學號_Q1.py"進行命名。設計一個可以顯示這個月日期與週次的月曆程式，透過time模組、datetime模組及相關的邏輯程式來運用(禁止使用calendar模組)。例如以下的執行結果：
```
>python Q1.py
April 2019
Mo      Tu      We      Th      Fr      Sa      Su
1       2       3       4       5       6       7
8       9       10      11      12      13      14
15      16      17      18      19      20      21
22      23      24      25      26      27      28
29      30
```

2. 建立一個程式，以"學號_Q2.py"進行命名。設計一個可以進行日誌記錄的程式，將DEBUG訊息：開始偵錯，以及INFO訊息：開始執行，寫入至日誌，並將結果存入data.log。例如以下的執行結果：
```
>python Q2.py

data.log中會有下列訊息

DEBUG:__main__:開始偵錯
INFO:__main__:開始執行
```
:::
![](https://i.imgur.com/PVqiWt5.jpg)

### [Numpy介紹與資料探索](https://drive.google.com/file/d/19iKsEFkEYndz7IoKmDDYeHKB7YqX2YIu/view?usp=sharing)
* 陣列
```python
import numpy as np #請不要忘記它
l1 = [12, 14, 0, 5, 23] #以下用這兩個list作為範例
l2 = [17, -5, 28, 5, 6]
a1 = np.array(l1)#轉換為numpy格式
a2 = np.array(l2)

# Part 1 
print(a1 + a2) #相同長度陣列可直接相加數值
>>> [29  9 28 10 29]

print(a1.ndim)# 顯示重要屬性
>>> 1
print(a1.shape)#尺寸(1*5的vector)
>>> (5,) 
print(a1.dtype)#型態
>>> int64

# Part 2 
a3 = np.array([1,2,3,4])
print(a3)
>>> array([1,2,3,4])
a3 = a3.reshape([2,2])#改成2*2方式呈現
print(a3)
>>> [[1,2],
	 [3,4]]

# Part 3 
a4 = np.zeros([2,3])
print(a4)
>>> [[0.0.0.],
	 [0.0.0.]]
a5 = np.ones([2,3])
print(a5)
>>> [[1.1.1.],
	 [1.1.1.]]
print(np.random.random((2,3)))#建立2*3 且數值在0-1之間的亂數
[[0.45458, 0.65132, 0.915135],
 [0.15564, 0.46294, 0.959726]]
print(np.linspace(2,10,5))#從2-10之間採樣五個數字
[2,4,6,8,10]
print(np.arange(2,10,2))#從2-10之間(不包含10)，步進為2
[2,4,6,8]
```
* 陣列索引、切片
```python
l1 = [12, 14, 0, 5, 23, 3]
a1 = np.array(l1)
print(a1)
>>> [12, 14, 0, 5, 23, 3]

print(a1[0:3])# 從第0個開始取，取到第3個之後不取
>>> [12 14  0]

print(a1[4:6])# 從第4個開始取，取到第6個之後不取
>>> [23  3]
```
* 基本操作
```python
l1 = [1, 2, 3, 4, 5, 6]
a1 = np.array(l1)
print(a1)
>>> [1, 2, 3, 4, 5, 6]

print(a1*2)# 就是變兩倍
>>> [2, 4, 6, 8, 10, 12]

print(a1+2)# 就是都加2
>>> [3, 4, 5, 6, 7, 8]
```
:::info
:bulb:Q&A
* 請寫出匯入NumPy模組的標準寫法？
* 請列出Ndarray的三個關鍵屬性？
* 在NumPy模組中，能改變陣列形狀與維度的方法是什麼？
* NumPy模組透過哪個方法，能順利的產生亂數的陣列資料？
* 在NumPy模組中，若建立[0,1,2,3,4,5,6,7]的陣列，並非透過array()方法協助，而是透過其他動態方法，該使用哪個方法及參數指定為何？
:::
:::success
:bulb:實作
* 建立一個程式，以"學號_Q1.py"進行命名。透過NumPy模組的協助，設計一個產生3組5個元素的亂數陣列，並讓亂數控制在1~39之間，以整數呈現，並輸出陣列內容的結果。例如以下的執行結果：
```
>python Q1.py
[[ 7 31 37 15 37]
 [ 2  3  7 15 30]
 [39 14 34 18 18]]
```
* 建立一個程式，以"學號_Q2.py"進行命名。透過NumPy模組的協助，設計一個自動產生1~16數字的程式，透過維度的調整，使其能以3維陣列來呈現，結果會是2*2*4的樣式。例如以下的執行結果：
```
>python Q2.py
[[[ 1  2  3  4]
  [ 5  6  7  8]]

 [[ 9 10 11 12]
  [13 14 15 16]]]
```
:::

## Week 4 (2/13 ~ 2/17)
### [Pandas介紹與探索資料](https://drive.google.com/file/d/1y-WCri9BdTS5DGBcfnhZDFaslAVLOm6T/view?usp=sharing)
> Pandas的設計宗旨是能夠處理異質性資料，例如在列欄試算表裡找到的東西；至於NumPy原本的設計是處裡同質性數值陣列，專供物理、電腦繪圖等等相關領域使用，然而Pandas很精明，能夠巧妙運用NumPy模組，發揮NumPy在效能方面的長處。
* 一維Series
```python
import pandas as pd
#建立Series
data = pd.Series([2, 4, 6, 8, 10], index = ["a", "b", "c", "d", "e"]) # 原始資料

#屬性
print(data.dtype) # 查看資料型態
print(data.size) # 查看資料筆數
print(data.index) # 查看資料索引

#查詢
data = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"]) # 自訂索引
print(data[0]) # 查看第一筆資料，按照順序
print(data["a"])# 查看第一筆資料，按照索引

#數值統計分析
print(data.sum()) # 列印出所有資料的和
print(data.mean()) # 列印出資料的中位數
print(data.std()) # 列印出資料的標準差
print(data.var()) # 列印出資料的變異數
print(data.prod()) # 列印出所有資料的乘積
print(data.max()) # 列印出資料的最大值
print(data.min()) # 列印出資料的最小值
print(data.nlargest(2)) # 列印出資料前兩大的值
print(data.nsmallest(2)) # 列印出資料前兩小的值

#字串分析
print(data.str.lower()) # 將所有字串的字母變成小寫列印出來
print(data.str.upper()) # 將所有字串的字母變成大寫列印出來
print(data.str.cat(sep = ",")) # 將所有字串串接，並用逗號隔開，列印出來
print(data.str.contains("a")) # 判斷各個字串是否包含"A"，列印初布林值
print(data.str.replace("a","A")) # 把各個字串中的"a"取代成"A"列印出來
print(data.str.len()) # 列印出每個字串的長度
```
* 二維(DataFrame)
>二維的資料，就像**表格**，DataFrame是由很多個Series組裝出來的，因此Series和DataFrame可互相轉換。因為是由Series組成，因此很多的寫法跟Series相似。
```python

#查看資料-1
data = pd.DataFrame({
    "fruit" : ["apple", "banana", "peach"],
    "price" : [10, 5, 30]
}, index = ["a", "b", "c"])

print(data["fruit"]) # 查看"fruit"的資料，一整行
print(data.iloc[0]) # 按照預設索引，查看第一列的資料
print(data.loc["b"]) # 按照自定義索引，查看"b"一整列的資料

#查看資料-2
data = pd.DataFrame({
    "fruit" : ["apple", "banana", "peach", "cherry", "coconut", "grape", "guava"],
    "price" : [10, 5, 30, 20, 50, 25, 15]
})


print(data.head()) # 如果沒有輸入數字，預設是5，即查看前五筆資料
print(data.tail()) # 如果沒有輸入數字，預設是5，即查看最後五筆資料
print(data.head(3)) # 查看前三筆資料
print(data.tail(3)) # 查看後三筆資料

#查看資料屬性
data = pd.DataFrame({
    "fruit" : ["apple", "banana", "peach", "cherry", "coconut", "grape", "guava"],
    "price" : [10, 5, 30, 20, 50, 25, 15]
})

print(data.size) # 查看資料的總資料數 
print(data.shape) # 查看資料的大小(即幾乘幾)
print(data.columns) # 查看所有的標題(key)
print(data.info()) # 查看所有資料的屬性，以每個Series顯示

#更改資料
data = pd.DataFrame({
    "name" : ["Justin", "Joyce"],
    "gender" : ["boy", "girl"],
    "score" : [59, 100]
}) # 原始資料

data.columns = ["Name", "Gender", "score"] # 更改標題，用此方法需要重新輸入所有標題，即使只需修改一個
data.rename(columns = {"score":"Score"},inplace = True) # 更改標題，只需更改要改變的值

data.loc[0, "Score"] = 30 # 修改第一列，"score"的值
data.loc[0] = ["Alice", "girl", 90] # 修改第一列全部的值

#更改索引
data = pd.DataFrame({
    "name" : ["Justin", "Joyce"],
    "gender" : ["boy", "girl"],
    "score" : [59, 100]
}) # 使用預設索引

data = pd.DataFrame({
    "name" : ["Justin", "Joyce"],
    "gender" : ["boy", "girl"],
    "score" : [59, 100]
}, index = ["a", "b"]) # 使用自定義索引

#增加新欄位
data = pd.DataFrame({
    "fruit" : ["apple", "banana", "peach"],
    "price" : [10, 5, 30]
})

data["cp"] = [3, 2, 5] # 利用list的方式，增加新的欄位
data["from"] = pd.Series(["Taipei", "Taichung", "Tainan"]) # 利用Series的方式，增加新的欄位

data.insert(2, "amount", 0) # 將"amount"插入在第二行，將初始值令為0
data["amount"] = [100, 300, 200]# 更改"amount"的值

#增加新欄位(列)
data = pd.DataFrame({
    "fruit" : ["apple", "banana", "peach"],
    "price" : [10, 5, 30]
}) # 原始資料

new_data = pd.DataFrame({
    "fruit" : "cherry",
    "price" : 20
},index = [3]) # 新的資料內容

data = data.append(new_data) # 加上新的資料

#刪除欄位(行及列)
data = pd.DataFrame({
    "name" : ["Justin", "Joyce"],
    "gender" : ["boy", "girl"],
    "score" : [59, 100]
}) # 原始資料

data.drop(["gender"], axis=1, inplace=True) # 以行為軸，刪除"gender"這一行

data.drop([0], inplace=True) # 以列為軸，利用預設的索引值，刪除第一筆資料
```
* 建立與儲存DataFrame
```python
#CSV
data = pd.read_csv("spilt0.csv")#匯入
data.to_csv("output.csv", index = False) # 將data輸出成csv檔，名稱叫"output.csv"#匯出
```
:::info
:bulb:Q&A

* 請問Pandas的設計宗旨是要能夠處理**異質性資料**，還是**同質性資料**？
* Pandas的核心概念是哪個元件的操作？
* Pandas模組是由哪一套模組延伸而來的？
* 在Pandas模組中，若要秀出前五個項目是透過哪一個方法？
* 在Pandas模組中，想要以位置來選出某一列時，是透過哪一個方法協助？

:::

:::success
:bulb:實作

* 建立一個程式，以"學號_Q1.py"進行命名。從政府資料開放平臺上，下載[糧價查詢](https://data.gov.tw/dataset/17092)的json資料集。透過Pandas模組的協助，挑選出108.4.15特定日期的交易數值。例如以下的執行結果：
![](https://i.imgur.com/3Ya5OoH.png)


* 建立一個程式，以"學號_Q2.py"進行命名。從政府資料開放平臺上，下載[糧價查詢](https://data.gov.tw/dataset/17092)的csv資料集。透過Pandas模組的協助，挑選108.5.17特定日期的資料，找出各縣市圓糯白米及長糯白米零售價格(pt_1glutrt、pt_1glutlt)。例如以下的執行結果：
![](https://i.imgur.com/pubZ2wc.png)

:::
### [Matplotlib資料視覺化1](https://drive.google.com/file/d/1b7t8d4-UQ-QdVpMlO7Pod2A-f5DTA17M/view?usp=sharing)

:::info
:bulb:Q&A
* 請問在Matplotlib模組中，有哪兩種控制圖表的模式？
* 在使用Matplotlib模組時，通常會需要怎麼進行import？
* Matplotlib預設使用哪種單位作為圖表尺寸單位？
* 如果想個別設定線條的標籤，可以透過哪個方法的協助？
* 若要繪製直條圖，需要透過哪個方法來幫忙？
:::
:::success
:bulb:實作
* 建立一個程式，以"學號_Q1.py"進行命名。從A[QI.json](https://drive.google.com/file/d/1FJo44ZC1XTbRIhUj7tD45OFCvLry0tUm/view?usp=sharing)中，透過Pandas取出斗六站(SiteName)的各個汙染源，製作成bar圖，其中標籤包括SO2、CO、O3、PM10、PM2.5、NO2、NOx、NO。例如以下的執行結果：

![](https://i.imgur.com/pGJ6Mlw.png)

* 建立一個程式，以"學號_Q2.py"進行命名。從[PM25.csv](https://drive.google.com/file/d/1sS1b_03uJLr6mP9K54KrHFsU98i4LyDd/view?usp=sharing)，透過Pandas模組的協助，挑選斗六(Site)的資料，找出資料中各個日期的PM2.5汙染值(Date、PM2.5_Mass_Concentration)，並以線條圖plot來繪製趨勢狀況。例如以下的執行結果：

![](https://i.imgur.com/Ryu04s4.png)

:::
### [Matplotlib資料視覺化2](https://drive.google.com/file/d/14eLg2iVUW9WCfDHakZXELlRkTy_ct0ky/view?usp=sharing)
```python
import numpy as np # 引入NumPy
from matplotlib.pyplot as plt # 引入matplotlib的函數
x = np.arange(20) # x軸的值
y = 3 * x + 1  # y軸的值
plt.title("practice") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.plot(x,y) # 繪製x,y軸的圖
plt.show() # 顯現圖形
```
![](https://i.imgur.com/LiJ0nJq.png)
```
title : 標題，即這個圖形名稱
xlabel : x軸的名稱，有時可以加註單位
ylabel : y軸的名稱，有時可以加註單位
plot : 繪製，建立好各自的座標後，利用plot進行繪製，
show : 顯示，利用plot繪製好的圖形是不會顯現出來的，需要用show才可以將圖形呈現出來
```
```python
#以上省略

#線的樣式 : $-$ 實線、$--$ 虛線、$:$ 點線-->第一張
plt.plot(x,y,ls = "--") # 繪製x,y軸的圖

#linewidth調整粗細-->第二張
plt.plot(x,y,linewidth = 5) # 繪製x,y軸的圖

#顏色改變-->第三張
plt.plot(x,y, color = "red") # 繪製x,y軸的圖
```
![](https://i.imgur.com/Qr5UY43.png)
![](https://i.imgur.com/WGMlu3o.png)
![](https://i.imgur.com/BvVstSK.png)

* 以下是各種常用圖-散佈圖、直方圖、長條圖、折線圖、圓餅圖
```python
#散佈圖
import matplotlib.pyplot as plt # 引入matplotlib的函數

x = [1,2,8,9,3,4,5,6] # x軸的值
y = [3,1,8,5,4,3,2,6]  # y軸的值

plt.title("scatter diagram") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.scatter(x, y) # 繪製散佈圖
plt.show() # 顯現圖形
```
![](https://i.imgur.com/ydAuQTr.png)
```python
#直方圖
import numpy as np # 引入NumPy
import matplotlib.pyplot as plt # 引入matplotlib的函數

data = np.random.normal(size = 50) # 產生50個常態分配的亂數
plt.title("histogram") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.hist(data)# 繪製直方圖
plt.show() # 顯現圖形
```
![](https://i.imgur.com/Otyu3wg.png)
```python
#長條圖
import numpy as np # 引入NumPy
import matplotlib.pyplot as plt # 引入matplotlib的函數

x = np.arange(1,11) # x軸的值
y = [3,1,8,5,4,2,4,6,3,7]  # y軸的值

plt.title("bar chart") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.bar(x, y) # 繪製長條圖
#plt.barh(x, y)橫的用barh
plt.show() # 顯現圖形
```
![](https://i.imgur.com/SggZ75X.png)
```python
#折線圖
import numpy as np # 引入NumPy
import matplotlib.pyplot as plt # 引入matplotlib的函數

x = np.arange(1, 9) # x軸的值
y = [3,1,8,5,4,3,2,6]  # y軸的值

plt.title("line chart") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.plot(x, y) # 繪製折線圖
plt.show() # 顯現圖形
```
![](https://i.imgur.com/YfRvHnA.png)

```python
#圓餅圖
import numpy as np # 引入NumPy
import matplotlib.pyplot as plt # 引入matplotlib的函數

category = ["clothing", "book", "meal", "snacks"] # 總類名稱
expand = [2000, 1500, 3000, 800]  # 圓餅圖的值
color = ["rea", "yellow", "blue", "green"] # 設定顏色

plt.title("pie chart") # 圖的標題
plt.xlabel("x axis") # x軸的名稱
plt.ylabel("y axis") # y軸的名稱
plt.pie(expand, label = category, color = color) # 繪製圓餅圖
plt.show() # 顯現圖形
```
![](https://i.imgur.com/nABBY6H.png)

:::info
:bulb:Q&A
* 請問在Matplotlib模組中，繪製散布圖需要透過哪個方法來幫助？
* 在Matplotlib模組的散布圖中，可以透過哪種簡單的預測模型，來找出兩個變數之間的關聯性？
* Seaborn模組是Matplotlib模組的延伸設計，通常習慣如何透過import來叫用它呢？
* Seaborn模組的許多函式，都能接受Pandas的哪種資料型態作為參數？
* Seaborn模組中若要綜觀不同維度的資料，我們通常會透過哪兩種圖示來協助？
:::
:::success
:bulb:實作
* 建立一個程式，以"學號_Q1.py"進行命名。從Seaborn的tips資料中載入資料，透過Pandas協助過濾資料，讓x軸為不抽菸的消費者的total_bill資料，讓y軸為不抽菸的消費者的tip資料，透過matplotlib.pyplot使用ax.scatter來繪製散布圖。設定圖內資料點size為x，及資料點color為x，資料點透明度為0.5，並讓圖表大小為4 x 4，並加入該圖的迴歸線。例如以下的執行結果：
![](https://i.imgur.com/5GTFsg3.png)
* 建立一個程式，以"學號_Q2.py"進行命名。從Seaborn的tips資料中載入資料，透過Pandas協助重新組合資料，挑選```total_bill```,```tip```,```size```,```sex```的資料，形成新的tips資料集。透過sns.PairGrid，挑選hue為```sex```， font_scale設定為1.5，並以直條圖與散布圖來觀察資料的狀況。例如以下的執行結果：
![](https://i.imgur.com/e3A2q4c.png)

:::

---

![](https://i.imgur.com/YKnZY2u.jpg)

---
## 恭喜各位!學到這邊已經變成資料科學大師囉~~ ^ ^ by 邱同學
## 答案

### Week 1
#### Python開發環境介紹、資料型態介紹
:::spoiler
- 請問在Python程式中，單行註解的符號是什麼？
```python
#
```
- 在撰寫Python程式時，若想引用其他套件的資源，可以透過哪個指令協助？
```python
import
```
- 若想知道某個資料的型態，可以用哪個函式協助查詢？
```python
type(變數名稱)
```
- 在Python中哪個資料的結構是無序，而元素是不重複的呢？
```python
set()
```
- 在Python中哪個資料的結構，是儲存鍵與值對應的呢？
```
dict(dictionary)
```
* 建立一個程式，以"學號_Q1.py"進行命名，提供使用者輸入三次字串資料，列出三次輸入資料中不重複的字串與數量。
![](https://i.imgur.com/BHR1UXi.png)
* 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入三次字串資料，列出輸入的所有字串。並提供一次查詢的輸入，來觀察資料是否曾經輸入。
![](https://i.imgur.com/dF2etF8.png)


* 請試著說明以下a,b,c,d四種變數的資料型態差別

```python
int
str
float
list
```
* `dict`的key與`list`的index中資料型態的比較
```python
numbers[3]
dict_number["3"]
```
:::
#### 說明Python程式運算子
:::spoiler
* 請問在Python程式中，想解決浮點數不精確的問題，可以透過哪個套件來協助？
```
decimal
```
* 在撰寫Python程式時，若想刪除變數，可以透過哪個指令協助？
```python
del
```
* 若想獲得整除的結果，可以用哪個運算子？
```python
//
```
* 在Python中’Hello’的字串str物件，若進行索引切片的運算，str[:2]會得到什麼結果呢？
```
0~2之間的資料(不包含2本身的資料)
```
* 在Python中，若想進行邏輯的運算，要如何得到"而且"的結果？
```python
and
```
* 建立一個程式，以"學號_Q1.py"進行命名，提供使用者輸入三次數字資料，列出三次輸入的加總結果。

![](https://i.imgur.com/xJ3bQmc.png)

* 繼續建立一個程式，以"學號_Q2.py"進行命名，提供使用者輸入二次字串資料，列出輸入的字串相加的結果。並提供一次索引切片數值的輸入，來進行資料的分割，分別判斷是否為小寫的資料。

![](https://i.imgur.com/CMDcpbf.png)

* 請試著不要直接用程式去跑，自行判斷以下值兩個print()會印出True還是False
```python
True
False
```
:::
### Week 2
#### Python流程語法
:::spoiler
* 請問在Python程式中，協助做選擇的結構是哪個名稱的程式區塊？
```python
if
```
* 在撰寫Python程式時，搭配bool型態進行控制的迴圈，是哪個名稱的程式區塊？
```python
while
```
* 若想取得迭代的內容指，可以用哪個名稱的程式區塊？
```python
for in
```
* 在Python中協助迭代結構增加索引的函數名稱為？
```python
enumerate
```
* 在Python中，若執行print(list(range(1,4)))，會得到什麼結果？
```python
[1, 2, 3]
```
實作1
```python
import random
a = int(random.choice(range(10)))
while True:
    g = int(input('猜一個數字:'))
    if g < a:
        print('比{0}大'.format(g))
    elif g > a:
        print('比{0}小'.format(g))
    else:
        print('你猜中了，就是{0}'.format(g))
        break
"""
猜一個數字:5
比5大
猜一個數字:8
比8小
猜一個數字:7
比7小
猜一個數字:6
你猜中了，就是6
"""
```
實作2
```python
name = input('請輸入您的名字：')

for i,n in list(enumerate(name,1))[::-1]:
    print(i,n)
```
挑戰
```python

names = ["Mackzine","Grace","William","Chiu","Cindy",
         "Arron","Tina","Karl","Clara"]
scores = [71,92,87,85,69,68,84,90,89]

for i,(name,score) in enumerate(zip(names,scores)):
    print(f"第{i+1}個拿考卷的是{name:<8},分數:{score}")
```

:::
#### Python函式設計
:::spoiler
* 請問在Python程式中，若要設計函式得使用哪個名稱的關鍵字來進行？
```python
def
```
* 在撰寫程式時，若設計了函式呼叫自身的作法，這做法稱之為何？
```
遞迴
```
* 在設計函式的過程中，若要提供不定數目的參數時，可以用哪個符號加註在前來提供功能？
```python
*
```
* 在Python中協助查詢區域變數名稱與值的函數名稱為？
```python
locals()
```
* 在Python中，若希望針對全域範圍的變數進行指定時，可用使用哪個關鍵字來協助宣告？
```python
global
```
實作1
```python
def area(x,y):
    return x*y

def peri(x,y):
    return (x+y)*2

x = int(input('請輸入長方形邊長：'))
y = int(input('請輸入長方形邊寬：'))
print('長方形面積：',area(x,y))
print('長方形周長：',peri(x,y))
```
實作2
```python
def BMI(h,w):
    b = w/h**2
    if b < 18.5:
        print('體重過輕，BMI：',b)
    elif 18.5<= b < 24:
        print('正常範圍，BMI：',b)
    else:
        print('體重過重，BMI：',b)

h = int(input('請輸入您的身高(公分)：'))/100
w = int(input('請輸入您的體重(公斤)：'))
BMI(h,w)
```
挑戰
```python
import numpy as np
input = [1,3,5,7,9]
def sigmoid(x):
    return [1.0/(1+np.exp(-k)) for k in x]

def softmax(x):
    return np.exp(x)/sum(np.exp(x))
    
print(f"sigmoid:{sigmoid(input)},softmax:{softmax(input)}")
```
:::
### Week 3
#### 常用內建模組

:::spoiler
:bulb:Q&A
* 請問Unix中，UTC的時間起始是哪個時間？
```
1970/1/1 00:00:00
```

* 在Python裡，datatime模組中有哪些類別來定義表示人類時間的概念？
```
date、time、datetime
```

* 在Python操作過程中，如果要讓datatime模組中時間使用ISO8601標準來顯示，需要透過哪一個方法來協助？
```python 
isoformat()
```

* Python中若要進行日誌的記錄，可以透過哪個模組來協助？
```python 
logging
```

* 在Python中日誌記錄分為哪幾種層級？
```
DEBUG、INFO、WRANING、ERROR、CRITICAL
```
:bulb:實作

Q1
```python
import time
from datetime import date

y = time.gmtime().tm_year
m = time.gmtime().tm_mon
d = 0
if m in (1,3,5,7,8,10,12):
    d = 31
elif m in (4,6,9,11):
    d = 30
else:
    if y%4:
        d=28
    else:
        d=29

print(date.today().strftime('%B %Y'))
print('Mo\tTu\tWe\tTh\tFr\tSa\tSu')
w = date(y,m,1).weekday()

for p_space in range(w):
    print(end='\t')
    
for p_day in range(1,d+1):
    print(p_day,end='\t')
    if (p_day+w) % 7 == 0 :
        print()
```

Q2
```python
import logging

logging.basicConfig(level=logging.DEBUG,filename='test.log')
logger = logging.getLogger(__name__)

logger.log(logging.DEBUG,'開始偵錯')
logger.log(logging.INFO,'開始執行')
```
```test.log```檔內容
```
DEBUG:__main__:開始偵錯
INFO:__main__:開始執行
```
:::
#### Numpy介紹與資料探索
:::spoiler
:bulb:Q&A

* 請寫出匯入NumPy模組的標準寫法？
```python
import numpy as np
```

* 請列出Ndarray的三個關鍵屬性？
```
維度(ndim)、形狀(shape)、數值型別(dtype)
```

* 在NumPy模組中，能改變陣列形狀與維度的方法是什麼？
```
reshape
```

* NumPy模組透過哪個方法，能順利的產生亂數的陣列資料？
````python
np.random.random()
````

* 在NumPy模組中，若建立[0,1,2,3,4,5,6,7]的陣列，並非透過array()方法協助，而是透過其他動態方法，該使用哪個方法及參數指定為何？
```python
np.arange(8)
```
:bulb:實作

Q1
```python
import numpy as np

a = np.random.random((3,5))*39+1
a = a.astype('int')
print(a)
```
Q2
```python
import numpy as np

a = np.arange(1,17,1)
a = a.reshape([2,2,4])
print(a)
```
:::

### Week 4

