iPAS AI 應用規劃師 中級 科目二 大數據處理分析與應用

seaborn barplot + pd.melt 比較四地區銷售比例

原題 46

團隊希望比較北美、歐洲、日本及其他地區的整體銷售比例,並使用 seaborn 套件以長條圖的形式進行可視化分析。請選出能正確顯示這些地區銷售總額比例的程式碼。

白話

資料集有四個地區銷售欄位(NA_Sales、EU_Sales、JP_Sales、Other_Sales),現在要用 seaborn 畫一張長條圖,x 軸是各地區名稱,y 軸是該地區的銷售總額,讓各地區的整體銷售量一目了然。

問你:哪一行程式碼能正確用 seaborn 長條圖呈現四個地區的銷售總額?

點選你的答案。

01 總結

一句話總結

要用 seaborn 的 barplot 比較四個地區的銷售總額,必須先用 pd.melt 把四個寬欄轉換成長格式,再傳給 sns.barplot 並用 estimator=sum 指定聚合為加總。countplot、lineplot、histplot 都不是正確的工具。

02 情境

先感受問題:seaborn 需要「長格式」資料

遊戲研究公司的分析師小凱要比較四個地區的銷售量。資料集目前是「寬格式」:

寬格式(原始):
Name NA_Sales EU_Sales JP_Sales Other_Sales
Wii Sports 41.49 29.02 3.77 8.46
Mario Kart 15.85 12.88 3.79 3.31

問題:seaborn 的 barplot 需要「長格式」資料,也就是 x 欄是地區名稱(variable),y 欄是銷售數值(value)。寬格式四個地區欄位無法直接傳給 seaborn。

解法:用 pd.melt 把寬格式轉成長格式,再傳給 sns.barplot 並用 estimator=sum 把同一地區的所有值加總成一根柱子。

長格式(melt 後):
variable value
NA_Sales 41.49
NA_Sales 15.85
...
EU_Sales 29.02
EU_Sales 12.88
...
03 對照

為什麼其他三種寫法都行不通

  1. countplot 不算數值加總:sns.countplot 計算「每個類別出現幾次」(計數),不計算銷售額數值的加總。即使能傳入欄位名稱,它也只計算頻率,不是銷售總額。而且 x=["NA_Sales",..] 傳入 Python 列表而非欄位名稱的用法本身就不符合 seaborn API。
  2. lineplot 是折線圖,y 不能是多欄列表:sns.lineplot 畫的是折線,適合時間序列,不是地區比較的柱狀圖。而且 y=["NA_Sales","EU_Sales",..] 傳入列表也不符合 seaborn 的 API(y 只接受單一欄位名稱)。
  3. histplot 是直方圖,顯示分佈而非總額:sns.histplot 畫的是「數值分佈的頻率」(例如各遊戲的 NA_Sales 分佈長什麼樣),不是四個地區的銷售總額比較。x 軸是銷售額的值域,不是地區名稱。
  4. seaborn 的 barplot 預設是 estimator=mean:不加 estimator=sum 時,barplot 預設顯示每個地區的「平均值」(每款遊戲平均賣多少),而非「總額」(所有遊戲加起來)。要顯示總額必須明確指定 estimator=sum。
  5. 寬格式不能直接用於多欄比較:seaborn 的設計哲學是長格式(tidy data):每行是一個觀察值,每欄是一個變數。要比較多個欄位,必須先 melt 成長格式再畫圖。
04 解法

melt 轉長格式,barplot + estimator=sum 搞定

小凱的正確程式碼:

melted = pd.melt(data, value_vars=["NA_Sales","EU_Sales","JP_Sales","Other_Sales"])
# melted 有兩欄:variable(地區名稱)和 value(銷售額)

sns.barplot(x="variable", y="value", data=melted, estimator=sum)
# x 軸:地區名稱(NA_Sales/EU_Sales/...)
# y 軸:每個地區的銷售額加總
# estimator=sum:指定柱子高度為加總而非預設的平均值

結果:四根柱子,x 軸是地區名稱,y 軸是全球各地區的銷售總額(百萬份),可直接比較各地區市場規模。這就是選項 C 講的:sns.barplot(x="variable", y="value", data=pd.melt(...), estimator=sum)

技術版:pd.melt 寬轉長格式與 seaborn barplot 精讀

中級考試大概率會考程式碼跟公式,所以這部分你還是要學。但如果現在學起來很痛苦,可以先跳過,等讀完其他題目回頭再來。

Step 1 純故事版

想像成績單:橫排有語文、數學、英文三列分數(寬格式),每位學生一行。melt 是把它改成直欄格式:第一欄「科目」、第二欄「分數」,每個分數獨佔一行(長格式)。長格式讓電腦容易按科目分組、加總、畫圖,seaborn 就是這種風格。barplot + estimator=sum 就是按科目把所有學生的分數加總,畫成柱子。

Step 2 中文 ↔ 程式碼對照
白話步驟程式碼
把四個地區欄位轉成長格式pd.melt(data, value_vars=[...])
長格式中地區名稱欄variable 欄(melt 的預設輸出欄名)
長格式中銷售數值欄value 欄(melt 的預設輸出欄名)
x 軸為地區名稱,y 軸為銷售值sns.barplot(x="variable", y="value", data=melted)
柱子高度為加總(非平均)estimator=sum
Step 3 符號角色表
pd.melt()
pandas 的寬轉長函式,把多個欄位(value_vars)折疊成兩欄:variable(原欄名)和 value(原欄值)。
value_vars
melt 中指定要折疊的欄位名稱列表,這些欄位會被轉成 variable 欄中的類別值。
sns.barplot()
seaborn 的分組長條圖,預設 estimator 是平均值(mean),可以改成 sum、max、np.median 等。
estimator=sum
指定 barplot 每根柱子的高度計算方式為加總,而非預設的平均值。需要注意 seaborn 版本,新版 API 略有差異。
tidy data(整齊資料)
seaborn 的最佳輸入格式:每行是一個觀察,每欄是一個變數,長格式就是標準的 tidy data 形式。
Step 4 完整公式對應

本題沒有數學公式,核心是資料形狀的轉換邏輯:

  • 寬格式(Wide format):每個特徵是一欄,適合 pivot 和矩陣運算
  • 長格式(Long/Tidy format):每個觀察一行,適合 seaborn、ggplot2 等視覺化工具
  • pd.melt = 寬轉長;pd.pivot_table = 長轉寬
Step 5 自我複述
  1. pd.melt 後產生哪兩個欄位?各代表什麼意思?
  2. sns.barplot 預設的 estimator 是什麼?要改成加總要怎麼寫?
  3. 為什麼 seaborn 需要長格式資料,而 pandas 的 plot 有時能直接用寬格式?
  4. countplot 和 barplot 的主要差別是什麼?各適合哪種問題?
  5. 如果想把 x 軸標籤從 "NA_Sales" 改成更易讀的 "北美",在 melt 之前或之後做哪個步驟?
05 陷阱

為什麼其他選項是錯的

選項 A sns.countplot

字面在說什麼:用 countplot 傳入四個欄位名稱,比較各地區。

為什麼不對:countplot 計算的是「某個類別欄位中每個值出現幾次」,不計算數值加總。而且 x=["NA_Sales","EU_Sales",..] 傳入 Python 列表根本不符合 seaborn API(x 要接受欄位名稱字串,不是欄位名稱的列表)。執行會報錯,完全不能用。

誰會選錯:把 countplot 和 barplot 搞混,以為兩個都能畫「各類別的數量/總額」長條圖的人。

選項 B sns.lineplot

字面在說什麼:用 lineplot 以平台為 x 軸,畫四個地區的銷售折線圖。

為什麼不對:lineplot 畫折線,不是長條圖。y=["NA_Sales","EU_Sales",..] 傳入列表也不符合 seaborn 的標準 API(seaborn 的 y 參數只接受單一欄位名稱字串)。而且題目要的是各地區整體銷售比較(4 根柱子),不是按 Platform 分組的折線趨勢。

誰會選錯:看到「視覺化」就想到折線圖,或不熟悉 seaborn API 規範的人。

選項 D sns.histplot

字面在說什麼:用 histplot 傳入四個地區欄位的 DataFrame,畫分佈圖。

為什麼不對:histplot 畫的是「數值分佈的直方圖」,x 軸是銷售額的值(0~50 百萬份等),y 軸是該值範圍內的遊戲數量。題目要的是每個地區的銷售總額比較(4 根柱子,x 軸是地區名稱),histplot 完全是不同的圖表類型,回答不同的問題。

誰會選錯:只要「能傳入多欄 DataFrame」就選的人,沒有判斷 histplot 回答的問題(分佈)和題目要求的問題(各地區總銷售比較)不同。

06 變形

同個考點下次怎麼變形

變形 1 邊界

直覺:pd.melt 的 id_vars 和 value_vars 有什麼差?

答案:id_vars 是「保留不折疊的欄位」(保持為識別符),value_vars 是「要折疊成長格式的欄位」。例如要同時保留 Name 和 Platform 兩欄:pd.melt(data, id_vars=["Name","Platform"], value_vars=["NA_Sales","EU_Sales","JP_Sales","Other_Sales"]),這樣 melt 後每行還能知道是哪款遊戲在哪個平台的哪個地區銷售額。

變形 2 反例

直覺:不用 pd.melt,能不能用其他方式讓 seaborn 畫出同樣的圖?

答案:可以先算好每個地區的總和,再手動建 DataFrame 傳給 seaborn:region_sales = data[["NA_Sales","EU_Sales","JP_Sales","Other_Sales"]].sum().reset_index();region_sales.columns = ["Region","Total_Sales"];sns.barplot(x="Region", y="Total_Sales", data=region_sales)。這樣不需要 estimator=sum,因為資料本身就已經是加總後的結果,每行就是一個地區的總銷售額。

變形 3 升級版

直覺:如果要按平台(Platform)分組,同時比較四個地區的銷售額,怎麼做?

答案:pd.melt 加入 id_vars=["Platform"],再用 sns.barplot(x="Platform", y="value", hue="variable", data=melted, estimator=sum)。hue="variable" 讓同一平台的四個地區用不同顏色的並列柱子呈現。這是 seaborn 分組長條圖(grouped bar chart)的標準做法。

變形 4 跨領域

直覺:pd.melt 在資料科學的哪些場景最常用?

答案:EDA 視覺化(比較多個欄位,需要轉長格式給 seaborn);機器學習前處理(OneHotEncoding 之前的多標籤欄折疊);時間序列分析(把多個時間點欄位轉成時間-值的長格式);問卷資料分析(把多個問卷題目欄轉成題目-答案長格式,方便統計各題的答案分佈)。melt 是「整理資料形狀」的重要工具,對應的逆操作是 pivot_table。

變形 5 評估指標

直覺:seaborn barplot 畫出來的圖上,除了柱子之外,還有什麼?代表什麼意思?

答案:預設有誤差線(error bar)。seaborn barplot 的誤差線預設是 95% 信賴區間(confidence interval),用 bootstrap 方法估算。這代表「我們估計該地區平均銷售額的範圍有 95% 的把握落在這個區間內」。如果改用 estimator=sum,誤差線就是總和的信賴區間。不想看誤差線可以設 errorbar=None 或 ci=None(舊版 seaborn)。

07 延伸

想再往下看,這 5 個

出處

iPAS 經濟部產業人才能力鑑定 ・ 114 年第二梯次 iPAS AI 應用規劃師 中級 科目二 大數據處理分析與應用 第 46 題

查看官方原文 PDF