看得懂一段統計程式:Python 基礎

先備知識 P1 — 選讀,不列入評分
變數名稱與物件參照|int float str bool|串列與索引|切片含頭不含尾|字典是鍵值對|f-string 與 format
向下捲動開始互動↓
📌 本頁使用方式(先備 · Python 基礎)

① 依序閱讀:每節先讀說明;遇到互動元件時,先預測結果,再操作驗證。 ② 對照程式範例:程式碼卡下方的「來源」標了課程練習筆記本(lab);需要實作時,再打開原始筆記本對照。 ③ 檢查理解:答錯時先看回饋,再回到相關說明;標為延伸的內容可留待第二輪。 ④ 最後用重點速查與來源複習。

教科書:An Introduction to Statistical Learning with Applications in Python(ISLP)。章節旁的來源標記可點到本頁書目。

CONTENTS · 內容目錄
PROLOGUE · 開場

先讓一段課程 lab 的程式碼變得看得懂 課程 Lab Ch2 · lab 範例

這一頁假設你完全沒寫過程式。目標很具體:讀完之後, 你能逐行讀懂課程 lab 的程式。後面幾頁再練習自己寫。

先從三件事讀程式 ① 算一個值;② 把值取個名字存起來;③ 把值丟給某個函式處理。閱讀課程 lab 時,先找出這三件事如何組合。
›按「單步」一行一行拆。
課程/lab 資料
一行一行拆
按「單步」把一段真的 lab 程式碼拆開,看每一行分別在做上面三件事的哪一件。
這一行
在做什麼—
屬於哪一類—
結果是什麼—
看不懂就唸出來
x = [3, 4, 5] 唸成「把一個裝了 3、4、5 的串列,取名叫 x」。程式碼是可以用中文唸的,唸得出來多半就懂了。
印出一行字
print('fit a model with', 11, 'variables')
預期輸出
fit a model with 11 variables

print 是一個函式,括號裡是要給它的東西,用逗號分開的話它會自動加空白。

來源:Ch02-statlearn-lab-zh.ipynb
算術
3 + 5
預期輸出
8

Jupyter 的儲存格會自動顯示最後一行的值,所以不寫 print 也看得到。

來源:Ch02-statlearn-lab-zh.ipynb
字串相加是接起來
"hello" + " " + "world"
預期輸出
'hello world'

加號對數字是相加、對字串是串接。這種「同一個符號、不同型別不同意思」的設計在 P3 的串列與陣列還會再遇到一次。

來源:Ch02-statlearn-lab-zh.ipynb
PART 00 · 自我檢測

print('MSE =', 25.57) 會印出什麼?

(A) MSE =25.57
(B) MSE = 25.57
(C) ('MSE =', 25.57)

遇到不熟的函式,先看呼叫方式

在 Jupyter/IPython 中,函式名稱後加 ? 可查看參數與說明;這是 notebook 的互動語法。 一般 Python 程式可用 help(print)。先找輸入參數、預設值、回傳值,再看範例,不必一次讀完整份文件。

在 notebook 查 print 的說明
print?

這格開啟說明面板;不假設 notebook 保存了文字輸出。

來源:Ch02-statlearn-lab-zh.ipynb
PART 01 · 變數與型別

變數名稱如何參照資料物件 課程 Lab Ch2 · lab 範例

可以把變數想成物件上的名牌。x = [3, 4, 5] 會先做出一個串列, 然後把 x 這個名牌貼上去。同一個東西可以貼很多張名牌—— P3 會用陣列的「檢視」示範共用資料時的修改結果。

›先猜按下「改內容」之後 x 會變成什麼。
概念示意
兩個名字指向同一個物件
按「再貼一張名牌」,兩個名字會指到同一個串列。接著按「改內容」,你會看到兩個名字看到的東西一起變了。
目前
x 看到的[3, 4, 5]
y 看到的(還沒有 y)
它們是同一個嗎—
數字與字串不會有這個問題
整數與字串是不可變的,a = 3; b = a; b = 4 之後 a 還是 3。會被就地改掉的只有串列、字典這種可變的東西。
型別長什麼樣在這門課裡是什麼
int392樣本數 n、變數個數 p、折數 k
float25.5739MSE、係數、p 值,幾乎所有統計量
str'lstat'欄名、檔名、圖的標題
boolTrue / False條件的結果,布林遮罩的元素
list[3, 4, 5]一組欄名、一組要試的參數
dict{'R2': 0.54}一組具名的結果
留意兩種除法的結果 7 / 2 給 3.5(浮點數),7 // 2 給 3(整數,直接砍掉小數)。算折數或索引時用得到後者,算統計量千萬不要用錯。
PART 02 · 串列

一排有順序的東西,從 0 開始數 課程 Lab Ch2 · lab 範例

串列是有順序的一排東西,用中括號寫,從 0 開始數。 課程 lab 裡最常見的用法是「一組欄名」與「一組要試的參數」。

做一個串列
x = [3, 4, 5] x
預期輸出
[3, 4, 5]
來源:Ch02-statlearn-lab-zh.ipynb
串列相加是接起來,不是逐元素相加
y = [4, 9, 7] x + y
預期輸出
[3, 4, 5, 4, 9, 7]

輸出有六個元素。要逐元素相加得用 NumPy 陣列。那是 P3 的第一節。

來源:Ch02-statlearn-lab-zh.ipynb
›按左右看每一個位置的索引。
概念示意
為什麼從 0 開始
把索引想成「離開頭有多遠」:第一個元素離開頭 0 步。這個想法在下一節的切片會變得很重要。
目前
索引0
取到的值'mpg'
負的索引-5
負的索引從後面數
-1 是最後一個、-2 是倒數第二個。要拿最後一欄寫 cols[-1],不用先算長度再減一。
你想做的事寫法
拿第一個cols[0]
拿最後一個cols[-1]
有幾個len(cols)
加一個到最後cols.append('mpg')
接上另一個串列cols + other 或 cols.extend(other)
在不在裡面'mpg' in cols
複製一份cols.copy()

tuple 與解包:一組不重新指派位置的值

tuple(元組)也是有順序的序列,例如 (2, 3) 可記錄兩列三欄。 串列可以用 x[0] = 9 更換某一項;tuple 的位置不能這樣重新指定。 只有一項時要寫 (2,),逗號才是關鍵;(2) 只是加括號的數字。

rows, cols = (2, 3) 叫做解包,兩個名稱依序取得 2、3,名稱數量須與項目相符。 之後 fig, ax = subplots() 也採用同樣的方式接住兩個回傳物件。 含有串列的 tuple 仍可讓那個內部串列改變;「tuple 不能改位置」不代表裡面每個物件都不可變。

來源:課程 Ch02 中文 Lab 的序列介紹與 reshape 說明(原始lab 範例);程式碼中的 shape 寫法見 NumPy 附錄。

PART 03 · 切片

起:迄:步長,而且迄不包含 課程 Lab Ch2 · lab 範例

切片是 起:迄:步長,而且迄不包含。 這個「不包含」讓很多人第一次用就錯,但它有個好處: a[:3] 加 a[3:] 剛好就是整個 a,中間不會重疊也不會漏。

›先猜 s[3:6] 會取到哪三個字。
課程/lab 資料
拖端點
按按鈕改起點、終點與步長,上面會標出被取到的字元。注意終點那一格永遠是灰的。它不包含在內。
目前
寫法s[3:6]
取到'lo '
長度3
同一套規則到處都是
字串、串列、NumPy 陣列、pandas 的 iloc 用的都是這一套。唯一的例外是 pandas 的 loc——它用名字,所以含尾(P4 會講)。
字串也能切
"hello world"[3:6]
預期輸出
'lo '

從第 3 個字元開始、取到第 6 個之前,三個字元,其中一個是空白。

來源:Ch02-statlearn-lab-zh.ipynb
另一種寫法:slice 物件
slice 物件是同一件事的另一種寫法
"hello world"[slice(3,6)]
預期輸出
'lo '

[3:6] 只是 [slice(3,6)] 的語法糖。知道這件事之後,「為什麼可以把切片存成變數」就不奇怪了。

來源:Ch02-statlearn-lab-zh.ipynb
PART 04 · 字典

透過鍵取得字典中的值 課程 Lab Ch1 · lab 範例

串列用位置取值,字典用名字取值。統計程式常用字典儲存「一組具名的結果」:模型的評分、欄名對應到型別、參數名稱對應到值。

課程應用:以字典建立 pandas 資料
用字典建一個 Series
sdata = {"Ohio": 35000, "Texas": 71000, "Oregon": 16000, "Utah": 5000} s3 = pd.Series(sdata) s3
預期輸出
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

鍵變成索引、值變成資料。pandas 可以用字典中的鍵和值建立 Series。

來源:Ch01-lab-zh.ipynb
›比較串列的位置與字典的鍵如何取值。
概念示意
兩種取值方式
左邊是串列(用位置),右邊是字典(用名字)。按按鈕看同一個查詢在兩邊怎麼寫,並比較用名字與位置取值時需要確認的資訊。
目前
要拿什麼—
串列寫法—
字典寫法—
鍵不存在會怎樣
d['沒有這個鍵'] 會拋 KeyError。不確定在不在就用 d.get('鍵', 預設值)——找不到時回傳預設值而不是報錯。
你想做的事寫法
取值d['R2']
安全取值d.get('R2', 0)
新增或覆寫d['MSE'] = 38.5
鍵在不在'R2' in d
所有鍵/所有值d.keys() / d.values()
一次拿鍵和值for k, v in d.items():
觀念釐清
字典的鍵可以是什麼?
鍵必須可雜湊(hashable):字串、數字通常可以;tuple 還需要每個元素都可雜湊。串列不行,因為它會變,變了之後就找不回原來的位置。實務上常用字串作為鍵。
字典有順序嗎?
Python 3.7 之後,字典會記住插入的順序,所以 for k in d 的順序是可預期的。需要排序時,明確使用 sorted(d)。
PART 04 · 自我檢測

scores = {'R2': 0.54},執行 scores['MSE'] 會怎樣?

(A) 拋 KeyError
(B) 回傳 None
(C) 自動建一個空的 MSE 項目
PART 05 · 字串與格式化

把數字變成人看得懂的一行字 課程 Lab Ch2 · lab 範例

最後一件事:把數字變成人看得懂的一行字。統計程式的輸出幾乎都要格式化—— 「MSE 是 25.573878189684412」沒有人想讀,你要的是「MSE 是 25.57」。

完整實作:逐欄格式化與迴圈輸出
format 與格式規格
for col in D.columns: template = 'Column "{0}" has {1:.2%} missing values' print(template.format(col, np.isnan(D[col]).mean()))
預期輸出
Column "food" has 16.54% missing values
Column "bar" has 25.98% missing values
Column "pickle" has 29.13% missing values
Column "snack" has 21.26% missing values
Column "popcorn" has 22.83% missing values

{1:.2%} 的意思是「第 1 個引數,用百分比、小數兩位」。所以 0.1654 印出來是 16.54%。這一格同時示範了迴圈與格式化。

來源:Ch02-statlearn-lab-zh.ipynb
迴圈裡的格式化
total = 0 for value in [3,2,19]: total += value print('Total is: {0}'.format(total))
預期輸出
Total is: 24

{0} 是「第 0 個引數」。現在更常見的寫法是 f-string:f'Total is: {total}',兩種都會遇到。

來源:Ch02-statlearn-lab-zh.ipynb
›同一個數字,五種格式。
課程/lab 資料
改格式規格看結果
同一個數字 25.573878,換不同的格式規格。按按鈕看每一種的輸出。
目前
格式規格{:.2f}
輸出25.57
什麼時候用報告統計量
f-string 是現在的預設寫法
f'MSE = {mse:.2f}' 把變數直接寫在字串裡,冒號後面接的格式規格跟 format 完全一樣。本站的程式碼卡兩種都會出現,因為課程 lab 兩種都用。
PART 05 · 自我檢測

'{:.2%}'.format(0.1654) 會印出什麼?

(A) 0.17%
(B) 16.54%
(C) 0.1654%
🔗 這在本站哪一章會用到 每一章的程式碼卡都在用這一頁的東西:串列裝欄名、字典裝評分、格式化把數字印成報告要的樣子。下一步是 P2 流程與函式,之後才是 P3 NumPy。
EXERCISES · 練習

動手驗證:概念自測 先備 · 自我檢測

回顧本頁觀念與原 Lab 的程式,確認各個操作的意義與使用條件。

EXERCISE 3 · 字典

你想記錄三個模型的 MSE,之後要能用模型名字查。該用什麼?

(A) 一個字典 {'linear': 25.57, 'quad': 22.22, 'cubic': 22.67}
(B) 三個變數 mse1、mse2、mse3
(C) 一個串列 [25.57, 22.22, 22.67]
EXERCISE 4 · 格式化

MSE 是 25.573878189684412,你想在報告裡印成兩位小數。哪一個寫法對?

(A) f'MSE = {round(mse)}'
(B) f'MSE = {mse:2f}'
(C) f'MSE = {mse:.2f}'
重點速查與來源

Python 基礎速查表 先備 · Python 基礎

來源:完整書目與章節定位

本頁書目與章節定位

  • 教科書:An Introduction to Statistical Learning with Applications in Python。James、Witten、Hastie、Tibshirani、Taylor,2023。原書與下載資訊

需要核對完整公式、比較表或實作時,再展開下方速查。

查閱完整速查與延伸提醒

三張速查表整理串列與字典、切片、格式規格。 Python 的「變數」是指向物件的名稱;統計資料的「變數」通常指一個測量特徵或欄位。 串列索引是位置;pandas 的 Index 可以是列標籤,兩者的對照見loc 與 iloc。

你想做的事串列字典
取一個a[0](位置)d['R2'](名字)
安全地取先 if len(a) > 0d.get('R2', 0)
加一個a.append(x)d['新鍵'] = x
有幾個len(a)len(d)
走過每一個for x in a:for k, v in d.items():
在不在x in a(比值)k in d(比鍵)
複製a.copy() 或 a[:]d.copy()
切片意思
a[2:5]索引 2、3、4(不含 5)
a[:3]從頭到索引 2
a[3:]從索引 3 到最後
a[:]整個,而且是新的一份
a[::2]每隔一個取一次
a[-1]最後一個
a[::-1]整個反過來
格式規格0.1654 印出來什麼時候用
{:.2f}0.17一般統計量
{:.4f}0.1654係數、p 值
{:.2%}16.54%比例、遺漏率
{:.3e}1.654e-01非常大或非常小的數
{:>10.2f}     0.17對齊成一欄
三個閱讀重點 1. 變數像貼在物件上的名牌。b = a 只是多貼一張名牌,改 b 會動到 a。
2. 索引從 0 開始,切片的迄不包含。所以 a[:k] 加 a[k:] 剛好是整個 a。
3. 串列用位置、字典用名字。有名字的資料可以用字典儲存,省去記「第 2 個是 MSE」這類位置對應。