Stanford Python程式課 - 第七週
第七週學習目標
- Lesson 18: Tuples and Sorting
- Lesson 19: Nested Structures
- Lesson 20: Nested Structures 2
- Assignment 6: Dictionary and Analyzing Data Bias
Assignment 6 結合之前學習的外部檔案讀取、資料處理、dictionary、tkinter繪圖等技能,很值得實作學習,附上作業的各個 milestones 的詳細說明,協助完成一個資料分析圖表呈現的程式。
Lesson 18 Tuples and Sorting
學習重點
- 學習 Python 中的 tuples
- 以 tuple 撰寫程式
- 學習 sorting
課程講義
Tuple 課程程式下載:tuple.zip
Lesson 19 Nested Structures
學習重點
- List: index -> value
- Dictionary: key -> value
- Reverse a dictionary
- XKCD color survey
課程講義
Nested Structures 課程程式下載:Nested Structures.zip
Lesson 20: Nested Structures 2
學習重點
- Mix and match lists and dictionaries
- json 檔案格式
課程講義
Nested Structures 2 課程程式下載:Nested Structures 2.zip
Assignment 6: Dictionaries and Analyzing Data Bias
此作業結合之前學習的檔案讀取、資料清理、資料處理、nested dictionaries、tkinter 繪圖等技能,非常建議依據 milestones 逐步完成,相信對於之前的幾個課程能有更完整的理解,畢竟學習程式最重要的就是實作!
作業下載連結:Assignment6.zip
作業重點:
- 熟悉 dictionary 操作
- 運用 tkinter 進行資料視覺化
- 作業分為兩部分
- 一、練習 以 function 處理 dictionary
- 二、透過 dictionary 處理、儲存網路上下載的資料,對資料進行搜尋、繪圖
作業內容
- 完成一個熱身練習題:data_analysis.py
- 完成一個由兩個完整的資料讀取、處理、具備搜尋及繪製圖表的程式
- 資料讀取、處理程式 biasbarsdata.py
- 繪圖視覺呈現程式 biasbars.py
作業熱身練習題:data_analysis.py
《 熱身題 data_analysis.py 目標 》
- 完成程式 data_analysis.py,熟悉資料處理、dictionary 運作
- 讀取檔案資料,創建 dictionary 儲存資料,key 為字串、value 為數字組成的 list
- 針對 dictionary 資料進行計算
《 問題說明 》
檔案 disease1.txt 內含不同地區的疾病感染資料,檔案內每一行的資料為:地區、7 個整數,7 個整數代表該地區前 7 天「累積」感染人數。
每一行的資料間以“ , ”區隔,但每一個數值前後可能有不一定數量的空格,disease1.txt 的範例如下:
Evermore, 1, 1, 1, 1, 1, 1, 1 Vanguard City,1 ,2 ,3 ,4 ,5 ,6 ,7 Excelsior ,1,1, 2, 3, 5, 8, 13
檔案內有三個地區,每一個地區有 7 個整數數字,代表該地區 7 天的累積感染人數,撰寫程式時可以假設檔案中的地區名稱為唯一。
《 Part 1: 檔案讀取 》
Part 1A: 完成 function
def load_data(filename)
功能是將上述資料格式的檔案 filename 讀入,將資料整理成為一個 dictionary,Key 是地區、Values 是該地區連續幾天的累積感染人數,以上述 disease1.txt 為例,產生的 dictionary 應該如下:
{ 'Evermore': [1, 1, 1, 1, 1, 1, 1], 'Vanguard City': [1, 2, 3, 4, 5, 6, 7], 'Excelsior': [1, 1, 2, 3, 5, 8, 13] }
Tips:
- strip() 可以移除一行字串後的換行符號"/n"、文字前後的空格
- split(',') 可以用來將 string 轉成 list
Part 1B: 完成 daily_cases function 計算每天受感染人數
def daily_cases(cumulative)
功能是將 load_data 整理完成的 dictionary (keys 是地區、values 是 7 個代表 7 天 的累積感染數組成的 list),計算後產生一個新的 dictionary,keys 跟原始輸入的 dictionary 相同,values 則為每日新增的感染人數。
例如 Part 1A 的 disease1.txt 經過處理後,產生的 dictionary 應該如下:
{ 'Evermore': [1, 0, 0, 0, 0, 0, 0], 'Vanguard City': [1, 1, 1, 1, 1, 1, 1], 'Excelsior': [1, 0, 1, 1, 2, 3, 5] }
Tips:
- 程式已經提供一部分 doctest,可以用來測試驗證完成的 function
- 兩個資料檔案:disease1.txt、disease2.txt 提供驗證程式正確性
主作業:分析資料偏差 biasbarsdata.py、biasbars.py
《 基本介紹 》
本作業運用之前學習的 nested data structure、tkinter 繪圖技巧,建立一個資料視覺化分析程式。
作業分成兩個程式 biasbarsdata.py、biasbars.py,biasbarsdata.py 負責資料處理、biasbars.py 負責將資料以圖表方式呈現。
分析的資料來自累積近 20 年的 RateMyProfessors.com 網站上的大學教授評價,Stanford 的學生在期末會填寫教授評鑑,提供後續學生選課的參考。
然而學生的教學評鑑,常常不能很客觀衡量教授的教學品質,近期研究顯示,教學評鑑甚至有明顯偏見,特別是對教授的性別偏見。
本作業的目標是建立一個資料分析程式,以圖表方式呈現學生的評鑑結果、分析評鑑使用的語言是否帶有性別偏見。
程式執行範例:
- 從資料檔案 full-data.txt 分析用字 “class” 對不同性別教授 (W: Women、M: Men) 的評鑑結果
圖表呈現 class 的評鑑結果,Source: 美股探路客 (增加每一直條圖右上方的數字標籤) |
- 從資料檔案 full-data.txt 分析用字 “funny” 對不同性別教授評價的結果
圖表呈現 funny 的評鑑結果,Source: 美股探路客 |
《 Overview:7 個 milestones 介紹 》
2~4 為完成資料處理的 biasbarsdata.py、5~7 為完成資料以圖表呈現的 biasbars.py
- 了解資料格式、處理並計算資料
- 撰寫一個 function,將單一用字 (word) 的評鑑資料處理後,儲存在提供的 dictionary
- 撰寫一個 function,處理整個評鑑資料檔案,並儲存在一個 dictionary 內
- 撰寫一個 function,對整個 dictionary 搜尋特定文字
- 執行提供的繪圖程式,確保與撰寫完成的資料處理間溝通正常
- 撰寫一個 function,繪製基本座標資訊
- 完成繪圖程式,將輸入的文字繪製成分析後的圖表,進行資料分析
《 Milestone 1:了解資料格式、處理並計算資料 》
RateMyProfessors.com 的評鑑資料範例如下圖,Quality 部分為 1-5 的數字,另外有例如 great teaching、awesome stuff 等描述性用語。
作業提供一個實際 2001~2018、17 年的 20,000 份評鑑資料的檔案,資料已經整理過成 txt 檔 (full-data.txt)。以下為一個測試用、較少資料的檔案 small-handout.txt 的內容
small-handout.txt: Rating,Professor Gender,Comment Text 5.0,M,mehran sahami is what stanford is all about 4.5,W,she is a great professor and is very knowledgeable 1.0,M,terrible aim his candy throwing needs to improve
- 第一行標示資料格式讓一般人能了解資料內容格式,讀取資料處理時應該忽略
- 之後內容以 3 個逗號 “ , ” 分隔,分別為 1.0~5.0 的評分 (5 代表最高評分)、性別 (M、W)、文字敘述 (已經將字串處理成小寫字母、去除標點符號)
《 Milestone 1:目標 》
- 完成 rating_stats.py 程式
- 讀取 data/full-data.txt
- 計算、輸出 (1) Women 評價超過 3.5 (high) 的百分比;(2) Men 評價超過 3.5 (high) 的百分比
- 百分比計算的分母為所有包含 Women、Men 的評價
- 轉換為百分比時,將計算所得的實數乘上 100 後,再以 python 內建的 round() function 轉換為整數
- 程式執行結果應該如下:
$ python3 rating_stats.py (範例為 PyCharm MacOS 的執行程式指令) Which data file would you like to load? data/full-data.txt 57% of reviews for women in the dataset are high. 58% of reviews for men in the dataset are high.
《 Milestone 2:建立 dictionary: "word_data" 》
- 完成 biasbarsdata.py 程式內的兩個 functions: add_data_for_word()、convert_rating_to_index()
- convert_rating_to_index(): 將學生評鑑分數 1.0~5.0 轉換為三個等級
- < 2.5 為 "low review"
- >= 2.5、<= 3.5 為 "medium review"
- > 3.5 為 "high review"
- add_data_for_word(): 將資料整理加入 dictionary "word_data" 中
- "word_data" 的資料結構
- key 為檔案內所有敘述性的評論文字
- value 為 nested dictionary,包含以性別 ('W' 或 'M') 為 key、value 則為該性別的評價結果
- 評價結果以 list 呈現,依序為 low reviews, medium reviews, high reviews
- word_data 的資料格式如下
{ 'great': { 'W': [30, 100, 800], 'M': [100, 200, 1500] }, 'teacher': { 'W': [330, 170, 852], 'M': [402, 250, 1194] } }
- biasbarsdata.py 已預先提供 KEY_WOMEN ("W")、KEY_MEN ("M") 兩個常數,代表 nested dictionary 內的 key
- 如果要讀取 word_data 內的資料,word_data["great"] 可以提供下面的 dictionary
{ 'W': [30, 100, 800], 'M': [100, 200, 1500] }
- word_data["great"]["W"] 則可得到下面的 list
[30, 100, 800]
- word_data["great"]["W"][2] 則可得到 Women 的 high review 評價數
800
- 為了方便 debug,程式已經提供 “print_word()” function,將資料依字母順序輸出,有興趣的話可以自行研究了解這個 function
- 下圖為 add_data_for_word 的運作範例,輸入包含 dictionary、性別標籤、評價結果 (word_data, "Gender", rating),add_data_for_word 將會被呼叫多次以建立完成的資料
add_data_for_word 運作範例 |
- 撰寫 add_data_for_word 時有三個考量的重點:
- 遇到第一次出現的敘述文字 (例如第一次出現 "great"),可以將以下的預設值存入 dictionary
default_dict = {
KEY_WOMEN: [0, 0, 0], KEY_MEN: [0, 0, 0] }
- 當遇到重複出現的敘述文字,應該根據對應的性別累計其評價,隨著遇到的次數越多,評價數累積越多
- biasbarsdata.py 內有一個 convert_rating_to_index(rating) function,建議完成並使用它以增加程式的可讀性,function 內已有幾個 doctest 供程式的驗證測試
- rating < 2.5, 回傳應該存入 list index 位置 0
- rating >= 2.5 & rating <= 3.5,回傳應該存入 list index 位置 1
- rating > 3.5,存入 list index 2,回傳應該存入list index 位置 2
《 Milestone 2 的驗證 》
biasbarsdata.py 程式內已提供多個 doctests 可以使用,測試從空的 word_data dictionary 輸入開始,驗證多個輸入資料的正確性,建議在撰寫 add_data_for_word() function 時添加自己需要的 doctest,協助驗證完成程式的正確性。
另外要注意的是 dictionary 中,key 的順序上 women 必須在 men 之前,否則將無法通過 doctest。
《 Milestone 3:處理完整的 review 資料 》
- 完成 biasbarsdata.py 程式內的 read_file() function
- Milestone 2 已經能運用 add_data_for_word function 將單筆資料加入 word_data dictionary 內,milestone 3 目的為將資料從檔案讀入、處理提供給 add_data_for_word
- 檔案資料格式:
- 第一行是描述資料格式,讀取時需要跳過
- 第二行開始,每一行代表一則 review 結果並以三個逗號 "," 區隔
- 第一個數字代表 review 分數,第二個代表性別,第三個為一段描述性的評論,建議使用 split(',') 來處理資料
- 描述性評論由許多文字組成,文字間為空格,同樣可以透過 split() 來處理,之後就可以運用 Milestone 2 完成的 add_data_for_word() 將資料儲存在 word_data dictionary
- Assignment 也提供 small-one.txt、small-two.txt、small-three.txt 三個較小的資料檔案供驗證程式使用
資料格式範例: Rating,Professor Gender,Comment Text 5.0,M,mehran sahami is what stanford is all about 4.5,W,she is a great professor and is very knowledgeable 1.0,M,terrible aim his candy throwing needs to improve ...
《 Milestone 4:在 dictionary 中搜尋特定文字 》
- 完成 biasbarsdata.py 程式內的 search_words( ) function
- 功能為提供一個 dictionary、特定的字串,搜尋並以 list 格式回傳 dictionary 中所有包含此特定文字的內容,例如 “great” 可以搜尋到 "great"、"greatest"、"Greater" 等
- 搜尋結果必須與英文大小寫無關 (case insensitive),例如 "gr" 跟 "Gr" 都應該得到同樣的結果
- 搜尋結果也必須與字串所在位置無關,例如輸入 "le",可以搜尋到 "lecture"、"middle" 等文字
《 Milestone 2~4 的驗證 》
到這邊已經完成整個作業的資料處理部分,作業提供的三個較小的資料檔案,可拿來驗證程式的正確性。
biasbarsdata.py提供的 main () 有兩種使用方法:
1. 執行時指定輸入的檔案位置及名稱
% python3 biasbarsdata.py data/small-three.txt average M [1, 3, 0] W [0, 0, 0] best M [1, 0, 0] W [0, 0, 3] not M [2, 0, 0] W [0, 0, 0]
2. 執行時除了指定輸入的檔案位置及名稱之外,增加搜尋的文字 "-search target"
% python3 biasbarsdata.py -search pand data/small-three.txt expanded expand expanding mind-expanding pandered expands pandering pander
至此,程式 biasbarsdata.py 已經完成,程式能夠完成的讀取、整理複雜的資料,接下來進入 biasbars.py 以圖表來呈現資料結果的環節。
《 Milestone 5:執行繪圖程式 》
- Milestone 5 無需撰寫程式
- 這階段主要是了解 biasbars.py 的架構,確認與完成的 biasbarsdata.py 間的溝通
- 提供的 biasbars.py 程式已經有基礎運作能力
- 透過 biasbargui.py (預先提供) 以 tkinter 產生繪圖 canvas、圖型介面接收輸入搜尋、繪製圖表所需文字的交互功能
- 透過 biasbarsdata.read_file() function 讀取資料檔,產生 word_data dictionary
- 請自行了解整個程式運作流程,執行程式後應該得到如下的畫面
% python3 biasbars.py
|
- 畫面看起來很簡單,但程式其實已經將之前 biasbarsdata.py 完成的所有資料載入,在下方 Search 空格可以輸入想搜尋的文字、後按 Enter,來測試 search_words() 程式的運作是否正常
- 下圖為在 Search 輸入 awes 後按 Enter 得到的結果
- 如果結果正確,Milestone 5 就順利完成了!
《 Milestone 6: 繪製圖表的固定內容 》
目標在 biasbars.py 內完成 draw_fixed_content( ) function,以在 Canvas 上繪製圖表的固定內容,包含圖表外框、評鑑品質的分類文字。
下面為程式已經提供,在 Miletsones 6、7 會使用到的 Constants :
VERTICAL_MARGIN = 30 LEFT_MARGIN = 60 RIGHT_MARGIN = 30 LABELS = ["Low Reviews", "Medium Reviews", "High Reviews"] LABEL_OFFSET = 10 BAR_WIDTH = 75 LINE_WIDTH = 2 TEXT_DX = 2 NUM_VERTICAL_DIVISIONS = 7 TICK_WIDTH = 15
下圖為 draw_fixed_content( ) 完成後執行 biasbars.py 得到的視窗
完成 draw_fixed_content( ) functin 後,執行 biasbars.py 得到的視窗 |
- tkinter 的 create_rectangle( ) 可以繪製需要的圖框
- 完成 get_centered_x_coordinate( ) function,因為draw_fixed_content( )、plot_word ( )(接下來的Milestone 7 完成) 都能重複使用,程式已經預先提供幾個 doctest 驗證正確性
- 每一個評鑑文字 (label) 都需要偏移圖框 LABEL_OFFSET 個 pixel
- tkinter 的 create_text( ) 可以繪製文字,anchor 參數可以指定文放置位置,例如 anchor=tkinter.N (請自行網路查閱用法)
- Main ( ) 預設視窗大小為 1000 x 600,請嘗試修改 WINDOW_WIDTH、WINDOW_HEIGHT 兩個常數改變視窗大小,確認完成的 draw_fixed_content( ) function 運作正常
《 Milestone 7: 將輸入的文字繪製成圖表 》
Milestone 7 為整個作業最後的部分,目標為完成 plot_word( ) function,在視窗中繪製文字出現頻率的長條圖、動態調整的 Y 軸標籤。
plot_word( ) function 中已經預先提供部分內容,透過之前完成的 draw_fixed_content( ) function 繪製圖框跟評價分類標籤、讀取 canvas 的 width、height,之後取得要繪製文字 word 在 word_data dictionary 出現的頻率 (max_frequency)。
plot_word( ) 每次在視窗左上角的 "Word To Plot:" 輸入框中輸入新的文字時,都會被執行一次,如果輸入的文字不在 word_data dictionary 時,視窗右上角會顯示提示訊息。
下圖為程式完成後執行的視窗結果及相關說明:
biasbars.py 程式完成後執行的畫面及相關說明 |
以下為幾項完成 milestone 7 的提示:
- 圖表 Y 軸需要利用 NUM_VERTICAL_DIVISIONS 來繪製所需的縱軸指標、對應的數字,指標長度為 TICK_WIDTH、寬度需與圖框相同 (可用 create_line( ) 來繪製指標)
- 每一個縱軸指標應該有對應的數字,最低的指標應該為 0,指標的數字可以透過 max_frequency 來計算,LABEL_OFFSET 用來設定指標數字距離座標軸的距離,create_text( ) 可用來繪製 需要的指標數字,anchor = tkinter.E 用來指定文字位於 x, y 座標的 right-center edge
- 圖表運用不同顏色的直條圖分別代表 women、men,women 的直條圖必須位於 men 直條圖的左側,範例圖中 women 使用 dogerblue 顏色代表,men 使用 orange
- 建議使用 get_centered_x_coordinate( ) 來計算直條圖的座標,讓每一組直條圖位在分類標籤的中間
- 每一個直條圖的左上角需要標示對應的性別 W 及 M,並在水平方向距直條圖左上角 TEXT_DX 的距離
- 如果在繪製圖表發現無法計算正確的座標,可以利用 console 輸出座標,不影響繪圖的視窗
- 最後如果搜尋文字 read、繪製文字 learn 的結果如下圖,恭喜你,程式已經撰寫完成!
最後正確執行 biasbars.py 的畫面,下方為搜尋文字的結果,上方為繪製直條圖的文字 |
延伸閱讀
未完待續 ...
0 comments