# 智慧數據研究所 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