投資、科技、生活


Stanford Code in Place - Python入門課程Week 7

Stanford Python程式課 - 第七週

第七週學習目標

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

  1. 了解資料格式、處理並計算資料
  2. 撰寫一個 function,將單一用字 (word) 的評鑑資料處理後,儲存在提供的 dictionary
  3. 撰寫一個 function,處理整個評鑑資料檔案,並儲存在一個 dictionary 內
  4. 撰寫一個 function,對整個 dictionary 搜尋特定文字
  5. 執行提供的繪圖程式,確保與撰寫完成的資料處理間溝通正常
  6. 撰寫一個 function,繪製基本座標資訊
  7. 完成繪圖程式,將輸入的文字繪製成分析後的圖表,進行資料分析

《 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

執行未修改的 biasbars.py 得到的視窗畫面 (Mac作業系統)

  • 畫面看起來很簡單,但程式其實已經將之前 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