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

## 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)

* 認識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
```

:::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
```
:::

### [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)}")
```
:::

### 補充
---
#### 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型別不一致。



>* [使用 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__:開始執行
```
:::

### [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特定日期的交易數值。例如以下的執行結果:

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

:::
### [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。例如以下的執行結果:

* 建立一個程式,以"學號_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來繪製趨勢狀況。例如以下的執行結果:

:::
### [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() # 顯現圖形
```

```
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軸的圖
```



* 以下是各種常用圖-散佈圖、直方圖、長條圖、折線圖、圓餅圖
```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() # 顯現圖形
```

```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() # 顯現圖形
```

```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() # 顯現圖形
```

```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() # 顯現圖形
```

```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() # 顯現圖形
```

:::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,並加入該圖的迴歸線。例如以下的執行結果:

* 建立一個程式,以"學號_Q2.py"進行命名。從Seaborn的tips資料中載入資料,透過Pandas協助重新組合資料,挑選```total_bill```,```tip```,```size```,```sex```的資料,形成新的tips資料集。透過sns.PairGrid,挑選hue為```sex```, font_scale設定為1.5,並以直條圖與散布圖來觀察資料的狀況。例如以下的執行結果:

:::
---

---
## 恭喜各位!學到這邊已經變成資料科學大師囉~~ ^ ^ by 邱同學
## 答案
### Week 1
#### Python開發環境介紹、資料型態介紹
:::spoiler
- 請問在Python程式中,單行註解的符號是什麼?
```python
#
```
- 在撰寫Python程式時,若想引用其他套件的資源,可以透過哪個指令協助?
```python
import
```
- 若想知道某個資料的型態,可以用哪個函式協助查詢?
```python
type(變數名稱)
```
- 在Python中哪個資料的結構是無序,而元素是不重複的呢?
```python
set()
```
- 在Python中哪個資料的結構,是儲存鍵與值對應的呢?
```
dict(dictionary)
```
* 建立一個程式,以"學號_Q1.py"進行命名,提供使用者輸入三次字串資料,列出三次輸入資料中不重複的字串與數量。

* 繼續建立一個程式,以"學號_Q2.py"進行命名,提供使用者輸入三次字串資料,列出輸入的所有字串。並提供一次查詢的輸入,來觀察資料是否曾經輸入。

* 請試著說明以下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"進行命名,提供使用者輸入三次數字資料,列出三次輸入的加總結果。

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

* 請試著不要直接用程式去跑,自行判斷以下值兩個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