跳到主要內容

DS 104 · 模組 1

探索資料:分布、變異與異常

從一份調查與結果資料集出發,練習用中心、分布、變異與異常值調查,回答「這個模式可信嗎?」而不是急著下結論。

開始第一節
已完成 0 / 5
同步我的進度加入梯次後,進度可跨裝置保存,講師也能看到

資訊

加入後,你已完成的模組編號會連同「學員代碼」傳送給講師,講師可以看到你的進度。請使用講師提供的代碼,不要輸入姓名、公司機密或其他個資。進度資料與該梯次的其他資料一起保存。

學習目標

  • 用 EDA 產生與檢查問題,而非證明預先設定的故事
  • 比較穩健與非穩健摘要,將統計量連回分布形狀
  • 描述離散程度,避免只用平均值解讀資料
  • 移除前先調查異常值,記錄理由並做敏感度比較
  • 建立分布、缺失、群組差異與可疑觀測的 EDA profile

EDA 的目的

25 分鐘

EDA 的目的:找模式,也找反例

學習目標:用 EDA 產生與檢查問題,而非證明預先設定的故事。

你的主管在看到一份調查摘要後說:「看起來 B 組的完成率明顯比較差,我們直接向委員會報告這個結論吧。」在你點頭之前,這正是探索式資料分析(EDA)該出場的時候:EDA 不是用來證明主管已經相信的故事,而是用來產生問題、尋找支持這個模式的證據,同時主動尋找會推翻它的反例。

先找證據支持結論

只挑出符合「B 組比較差」這個說法的幾筆數字,做成一張圖,然後停止分析。

先用 EDA 產生與檢查問題

產生問題
這個差異在整體資料中有多大?是所有子群一致,還是被少數觀測拉動?
尋找反例
有沒有任何分層或子群,結果和整體模式相反?
檢查資料品質
這個模式會不會其實是缺失值、未完成回覆或抽樣層分布不均造成的?
本課程的資料集(先載入,下結論前先問問題)
import pandas as pd

# clean:一份調查與結果資料集,一列代表一筆觀測
df = pd.read_csv("DS104_Survey_Outcomes_Clean.csv")
df.shape
df.head()
df["group"].value_counts()

# 主管的說法:B 組的 outcome 比較低。先看整體,而不是只看一張圖
df.groupby("group")["outcome"].mean()
同一句話,兩種問法
證明式問法EDA 式問法
「證明 B 組比較差。」「B 組與 A 組的 outcome 平均值差多少?這個差異在每個 age_band、每個 sampling_stratum 都一致嗎?」
「找出支持這個結論的圖表。」「有沒有任何子群的結果和整體模式相反?如果有,為什麼?」
同一份資料,兩種結論(模擬情境)

整體來看,B 組的 outcome 平均值確實比 A 組低了 6 分,乍看支持主管的說法。但分 age_band 檢查後發現,差異幾乎全部集中在最年輕的那一個分層;在其他三個年齡分層中,A 組與 B 組的平均值幾乎相同。只看整體數字會把「這是哪一群人的差異」這個關鍵問題藏起來,而這正是 EDA 要主動挖出來的反例。

  • 先寫下想回答的問題,再開始畫圖或算統計量,避免邊做邊換問題
  • 對任何「A 比 B 好/差」的說法,至少換一個切分方式(分層、年齡、完成狀態)重新檢查一次
  • 主動找出和整體模式相反的子群,並記下它們佔整體資料的比例
  • 把「資料顯示什麼」與「資料品質是否足以支持這個說法」分開來寫

注意

資料安全提醒:本課程所有練習都使用課程提供的合成資料。除非獲得授權,切勿將機密的機構資料、客戶個人資料或未經授權的敏感資訊貼入 AI 工具或練習環境。

資訊

Human, AI, Human:人負責設定分析問題並決定要不要接受一個模式;AI 可以協助計算分組統計量或畫圖;人負責檢查是否找過反例,再把結論交出去。
自我檢測

主管已經認定「B 組表現比較差」,並請你做圖表來支持這個說法。以下哪一種做法最符合 EDA 的目的?

主管已經認定「B 組表現比較差」,並請你做圖表來支持這個說法。以下哪一種做法最符合 EDA 的目的?

重點: 能完成步驟不代表結果可信;本節的能力必須能被驗證、重做並清楚說明。

中心與分布

35 分鐘

中心與分布:Mean、Median、Percentile

學習目標:比較穩健與非穩健摘要,將統計量連回分布形狀。

同事回報:「outcome 的平均值是 62,看起來還不錯。」但如果資料中有少數幾筆極端值(例如少數觀測的 outcome 遠高於或遠低於其他人),平均值會被這些極端值拉動,讓「還不錯」這個判斷失真。中位數(median)與百分位數(percentile)能提供不受極端值主導的另一種視角。

Mean(平均值)

  • 把所有數值加總後除以筆數
  • 每一筆觀測都會影響結果,包含極端值
  • 在對稱、沒有極端值的分布中最直觀

Median(中位數)

  • 排序後最中間的那個值
  • 極端值最多只能把它推向下一個排序位置,不會被拉遠
  • 在偏態分布或有極端值時更能代表「典型」觀測
比較 mean 與 median,並看百分位數
summary = df["outcome"].describe(percentiles=[0.25, 0.5, 0.75])
print(summary)

mean_val = df["outcome"].mean()
median_val = df["outcome"].median()
gap = round(mean_val - median_val, 2)
# gap 越大,代表分布越偏態,或有少數極端值正在拉動平均值

p10, p90 = df["outcome"].quantile([0.1, 0.9])
# 第 10 與第 90 百分位數:90% 的觀測落在這個範圍之內
mean 與 median 差距透露的訊息
情況mean 與 median 的關係可能的解讀
分布大致對稱、無極端值mean ≈ median用 mean 描述中心通常沒有問題
少數觀測值遠高於其他人(右偏)mean > median平均值被少數高值拉高;median 更能代表典型觀測
少數觀測值遠低於其他人(左偏)mean < median平均值被少數低值拉低;median 更能代表典型觀測
62 分背後的兩種可能(模擬情境)

情境一:outcome 的 mean 是 62,median 也是 61,兩者相近,代表「還不錯」這個說法大致可信。情境二:mean 同樣是 62,但 median 只有 48,差距高達 14 分,代表大多數觀測其實落在 50 分以下,只有少數偏高的觀測把平均值拉上去。同一個 mean,兩種情境需要完全不同的報告方式。

  • 任何時候要報告 outcome 的「中心」數字,先同時算出 mean 與 median,再決定要主打哪一個
  • mean 與 median 的差距超過原始量表的 5% 到 10%,通常值得畫一張直方圖確認分布形狀
  • 對外溝通時,與其只說一個數字,不如說「大多數觀測落在哪個範圍,少數觀測如何偏離」
  • 百分位數(如 p10、p90)比單一的 mean 或 median 更能呈現資料的整體分布樣貌

注意

只報告一個平均值而不看分布形狀,是最容易誤導決策的做法之一:兩個平均值相同的資料,可能有完全不同的分布,因此需要完全不同的因應方式。
自我檢測

某資料集的 outcome 絕大多數觀測落在 40 到 60 之間,但有兩筆觀測值高達 300(其餘資料看起來正常)。在決定要向委員會報告哪一個「中心」數字時,哪一個做法最恰當?

某資料集的 outcome 絕大多數觀測落在 40 到 60 之間,但有兩筆觀測值高達 300(其餘資料看起來正常)。在決定要向委員會報告哪一個「中心」數字時,哪一個做法最恰當?

重點: 能完成步驟不代表結果可信;本節的能力必須能被驗證、重做並清楚說明。

變異

35 分鐘

變異:Range、IQR、Standard Deviation

學習目標:描述離散程度,避免只用平均值解讀資料。

兩個分層的 outcome 平均值都是 55,聽起來像是同一種情況。但如果 A 分層的觀測全部集中在 50 到 60 之間,B 分層的觀測卻從 10 散布到 100,這兩種資料代表的風險完全不同:只報告平均值會把這個差異完全藏起來。

三種常見的離散程度指標
指標計算方式對極端值的敏感度適合的情境
Range(全距)最大值減最小值極度敏感:單一極端值就能大幅改變它快速檢查資料範圍,不適合單獨作為結論
IQR(四分位距)第 75 百分位數減第 25 百分位數不受少數極端值影響,只看中間 50%偏態分布或已知有異常值時的首選
Standard Deviation(標準差)每筆觀測與平均值差距平方的平均,再開根號對極端值敏感,因為用了平方大致對稱、無明顯極端值的分布
同一個平均值,用變異指標看出差異
by_stratum = df.groupby("sampling_stratum")["outcome"].agg(
    mean="mean",
    std="std",
    q25=lambda s: s.quantile(0.25),
    q75=lambda s: s.quantile(0.75)
)
by_stratum["iqr"] = by_stratum["q75"] - by_stratum["q25"]
by_stratum["range"] = df.groupby("sampling_stratum")["outcome"].agg(lambda s: s.max() - s.min())
print(by_stratum)
# mean 相近,但 std 與 iqr 差很多,代表兩個分層的離散程度不同

注意

只報告平均值而不報告任何離散程度指標,等於隱藏了「這個平均值背後的觀測有多一致」這個問題。決策者需要知道結果是穩定聚集在平均值附近,還是散布得很廣。
  • 報告任何平均值時,至少搭配一個離散程度指標(IQR 或標準差)
  • 分布可能有極端值或明顯偏態時,優先使用 IQR 而不是標準差
  • Range 對單一極端值極度敏感,只適合快速檢查,不適合作為結論依據
  • 比較兩個群組時,先比較各自的離散程度,再比較平均值是否有意義
選錯離散程度指標會怎樣(模擬情境)

exposure 欄位中有一筆觀測是其他人的十倍。如果用 range,這一筆就能讓全距暴增好幾倍,讓人誤以為整體資料都很分散;如果改用 IQR,中間 50% 的觀測其實聚集得很緊密,只有這一筆極端值例外。選哪個指標,會直接決定你對「資料到底有多分散」這個問題的答案。

  1. 先畫出分布
    用直方圖或箱型圖看一眼形狀,判斷是否明顯偏態或有極端值。
  2. 依形狀挑指標
    大致對稱、無極端值時可用標準差;偏態或有極端值時優先用 IQR。
  3. 兩個指標都算一次
    即使只打算報告一個,也先算出另一個做對照,確認兩者說的故事是否一致。
自我檢測

A 分層與 B 分層的 outcome 平均值都是 55。A 分層的標準差是 3,B 分層的標準差是 28。以下哪一個描述最正確?

A 分層與 B 分層的 outcome 平均值都是 55。A 分層的標準差是 3,B 分層的標準差是 28。以下哪一個描述最正確?

重點: 能完成步驟不代表結果可信;本節的能力必須能被驗證、重做並清楚說明。

Outlier 調查

35 分鐘

Outlier:錯誤、例外或重要訊號?

學習目標:移除前先調查異常值,記錄理由並做敏感度比較。

你在檢查 exposure 欄位時,發現一筆觀測的數值是其他人的十倍。直覺反應可能是「這一定是錯的,刪掉它」,但異常值可能是三種完全不同的情況:資料輸入或量測錯誤、罕見但真實的例外情況,或是揭露某個重要現象的訊號。在你決定怎麼處理之前,必須先調查它是哪一種。

異常值的三種可能來源與對應行動
可能來源如何判斷建議行動
錯誤(量測或輸入)數值在物理上或邏輯上不可能,或與 response_complete、weight 等欄位矛盾記錄理由後修正或排除,並在報告中說明
例外(罕見但真實)數值極端但邏輯上可能,且與其他欄位(如 age_band、group)一致保留,但在分析中特別標註,必要時分開呈現
訊號(重要現象)多筆觀測呈現類似的極端模式,而不是單一個案不要當成雜訊移除;進一步調查這群觀測背後的原因
用 IQR 規則標出候選異常值,調查後再決定
q1, q3 = df["exposure"].quantile([0.25, 0.75])
iqr = q3 - q1
lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr

flagged = df[(df["exposure"] < lower) | (df["exposure"] > upper)]
flagged[["observation_id", "exposure", "group", "response_complete", "sampling_stratum"]]
# 先看這些觀測的其他欄位,再判斷是錯誤、例外還是訊號
  1. 用規則標出候選
    用 IQR 規則(低於 Q1 − 1.5×IQR 或高於 Q3 + 1.5×IQR)列出候選異常觀測,先不要刪除任何資料。
  2. 檢查上下文
    查看每一筆候選觀測的其他欄位(response_complete、weight、age_band),判斷數值是否邏輯一致。
  3. 做敏感度比較
    分別計算包含與排除這些觀測時的 mean、median 與 IQR,看看結論是否因此改變。
同一種極端值,三種不同判斷(模擬情境)

A 分層中被標出的那筆 exposure 極端值,weight 欄位是負數,邏輯上不可能,查證後確認是輸入錯誤,應記錄並修正。B 分層中被標出的一筆,weight 與 age_band 都正常,只是數值恰好落在分布的最邊緣,屬於合理但罕見的例外,應保留並標註。C 分層中被標出的五筆觀測,彼此的 age_band 都相同,且都發生在同一段抽樣期間,這更像是某個群體真實呈現的訊號,需要再深入調查而不是直接排除。

  • 單一極端值 vs. 一群相似的極端值:前者更可能是個案,後者更可能是訊號
  • 極端值是否與其他欄位(weight、response_complete)邏輯矛盾,矛盾通常指向錯誤
  • 排除任何觀測前,先確認排除後的結論與排除前是否不同;如果結論不變,排除與否的影響有限
  • 把「調查過程」和「調查結論」都寫進報告,而不是只呈現排除後的乾淨結果

注意

沒有記錄理由就移除異常值,等於用直覺悄悄改變了結論,而且無法重現。任何排除都必須寫下依據,並附上排除前後的敏感度比較。
自我檢測

你用 IQR 規則標出一筆 exposure 極端值。發現這個資料的第一步應該是什麼?

你用 IQR 規則標出一筆 exposure 極端值。發現這個資料的第一步應該是什麼?

重點: 能完成步驟不代表結果可信;本節的能力必須能被驗證、重做並清楚說明。

Guided Lab

50 分鐘

Guided Lab:建立 EDA Profile

學習目標:在教師引導下,建立分布、缺失、群組差異與可疑觀測的 EDA profile。

資訊

實作問題:如果你只有十分鐘可以跟利害關係人報告這份資料,你會如何用一份精簡的 EDA profile,涵蓋分布、缺失、群組差異與可疑觀測,交代這份資料值不值得信任?
  1. 載入並檢視 schema
    載入乾淨版資料,檢查列數、欄位型別,以及 group、age_band、sampling_stratum 的類別內容。
  2. 檢查缺失與未完成回覆
    計算每個欄位的缺失比例,以及 response_complete 為否的觀測占比,並看它是否集中在特定分層。
  3. 建立分布摘要
    對 outcome 與 exposure 計算 mean、median、IQR 與標準差,並畫出直方圖檢查形狀。
  4. 比較群組差異
    依 group 與 age_band 計算 outcome 的平均值與離散程度,記錄任何看起來不一致的子群。
  5. 標出可疑觀測
    用 IQR 規則標出候選異常值,選一筆實際調查其上下文,並記錄你的判斷。
  6. 寫下仍需人工判斷的項目
    列出這份 profile 還無法回答、需要進一步確認或人工判斷的問題。
EDA profile 應包含的最少內容(請填入你自己的輸出結果)
項目要回報的內容
形狀與 schema列數、欄位型別、各類別欄位的允許值
缺失與完整性各欄位缺失比例,以及 response_complete 為否的觀測分布
分布outcome 與 exposure 的 mean、median、IQR、標準差與直方圖
群組差異依 group 與 age_band 分組後的中心與離散程度是否一致
可疑觀測被標出的候選異常值,以及調查後的判斷(錯誤/例外/訊號)
一個欄位,兩種寫法

弱寫法:「C 分層的完整性比較差。」強寫法:「C 分層的 response_complete 為否的比例是 34%,是其他三個分層平均值(9%)的將近四倍;在解讀 C 分層的 outcome 時,應假設這個數字可能偏向已完成回覆的那群人。」第二種寫法附上了具體數字、比較基準,以及對結論的實際影響,才算是一份可被檢視的 EDA profile。

  • 只呈現最後的乾淨圖表,沒有交代途中排除了哪些觀測、依據是什麼
  • 把「平均值不同」直接寫成「兩組不一樣」,卻沒有提到各自的離散程度
  • 只檢查了整體資料,沒有依 group、age_band 或 sampling_stratum 分開確認同一個模式是否一致
  • 把本節練習中仍無法回答的問題省略不寫,讓報告看起來比實際上更有把握

注意

「程式碼有跑出結果」不等於「這份 profile 可信」。每一個數字都必須能被重新執行、能被說明它的計算方式,而且任何排除或特殊處理都要有記錄。

完成

如果 AI 協助計算摘要統計量或畫圖,請自己逐項檢查:分組是否正確、離散程度指標是否對這個分布合適、以及任何被標出的異常值是否已經被調查而不是直接忽略或刪除。AI 可以加快草擬速度;驗證與結論仍是人的責任。
自我檢測

你完成了一份 EDA profile,發現 C 分層的 response_complete 為否的比例遠高於其他分層。這個發現最適合如何處理?

你完成了一份 EDA profile,發現 C 分層的 response_complete 為否的比例遠高於其他分層。這個發現最適合如何處理?

重點: 能完成步驟不代表結果可信;本節的能力必須能被驗證、重做並清楚說明。

接下來做什麼?