跳到主要內容

DS 101 · 模組 1

從 ESG 問題到 Python 資料分析

你想回答什麼問題?手上的資料又能支持到哪裡?

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

資訊

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

學習目標

  • 把模糊的 ESG 問題轉成可由資料回答的問題,並說出 Question、Measure、Dimension 與 Evidence boundary
  • 說明 row、column、observation、variable、dimension、measure、metric 與 unit,並區分絕對指標與強度指標
  • 在 Notebook 中依正確順序執行基本 Python 與 pandas 程式碼,並能讀懂錯誤訊息
  • 使用 pandas 檢查、選取、篩選與排序資料,並在每一步之後驗證結果
  • 完成第一次 Guided Lab:計算 Scope 1+2 排放量與排放強度,並把觀察分成事實、解讀與待查證

問題與資料

30 分鐘

從 ESG 問題到資料問題

學習目標:學會先定義「要回答什麼」,再決定需要什麼資料與分析方法。

Data Science 的起點不是 Python,而是問題。如果問題本身很模糊,程式寫得再漂亮,得到的也只是一堆沒有方向的數字。因此本課程的第一步,是把一句籠統的疑問,改寫成資料能夠回答的具體問題。

模糊的問題

我們公司的 ESG 表現好不好?(「好」的定義是什麼?和誰比?看哪一年?用哪些數字?都沒有說清楚。)

可以由資料回答的問題

變化
2021–2025 年 Scope 1 + 2 排放量如何變化?
比較
哪一年的排放強度最高?
另一種解釋
排放下降,是因為效率改善,還是只是因為營收下降?
資料品質
哪些公司或年度需要進一步檢查資料品質?
把問題變成資料問題的四個基本構件
構件要問自己的問題範例
Question我到底想回答什麼?2021–2025 年 Scope 1 + 2 排放量如何變化?
Measure要計算或比較哪一個數值?單位是什麼?scope1_tco2e + scope2_tco2e,單位 tCO2e
Dimension要按公司、年度或其他類別比較嗎?依 company_name 與 year 分開看
Evidence boundary現有資料能支持到什麼程度?哪些事情它回答不了?資料可以描述排放如何變化,但無法單獨證明變化的原因
DS 101 的學習循環
  1. Question:先寫下要回答的問題
  2. Data:確認需要哪些欄位、單位與範圍
  3. Python:用最少必要的程式碼處理資料
  4. Analysis:計算指標並比較
  5. Verification:檢查公式、單位、輸出與說法
  6. Communication:寫出證據與限制

注意

資料安全提醒:未經授權,請勿把機構或公司的機密資料、客戶資料或任何個人資料貼到 AI 工具中。本課程所有練習一律使用課程提供的模擬資料檔;若日後要分析真實的 ESG 或內部營運資料,請先確認所屬單位的資料使用規範。

資訊

先問題、後程式碼。AI 可以協助你把問題拆得更清楚,但「要回答什麼」由你定義,最後的結論也由你審查並負責。
  • 有沒有時間範圍?例如「最近」要换成具體年度,如 2021–2025 年。
  • 有沒有比較對象?例如是和自己過去比,還是和其他示範公司比。
  • 有沒有講清楚單位?例如「排放量」要講清楚是 tCO2e,還是強度指標。
  • 有沒有說明資料的邊界?例如這份資料只到 2025 年,無法回答之後會怎樣。
示範:把一個「還不夠具體」的問題再收斂一次

主管問:「Metro Services Co. 做得怎麼樣?」這句話還不能直接用資料回答,因為沒有比較對象、時間範圍與指標。收斂後:Question(2023–2025 年 Metro Services Co. 的 Scope 1+2 排放強度,和其他三家示範公司相比是偏高還是偏低?)、Measure(scope1_tco2e + scope2_tco2e,除以 revenue_m_twd)、Dimension(依 company_name 與 year 比較)、Evidence boundary(資料只能描述相對高低,無法解釋造成差異的原因)。

自我檢測

哪一個問題最適合直接用結構化 ESG 資料回答?

哪一個問題最適合直接用結構化 ESG 資料回答?

重點: 先定義問題,再寫程式。資料分析的品質從問題設定開始。

30 分鐘

認識 ESG Dataset 與指標

學習目標:理解 row、column、observation、variable、dimension、measure、metric 與 unit。

本課程使用 DS101_ESG_Company_Data_Clean.csv。這是教學用的模擬資料:四家示範公司(Alpha Tech Co.、Harbor Foods Co.、Evergreen Components Co.、Metro Services Co.),每家 2020 至 2025 年各一列,共 24 列。公司名稱與數值都是為了教學而設計,並不代表任何真實公司。

示意表:資料的樣子(數值僅為說明而編寫,並非課程檔案中的實際數值)
company_idcompany_namesectoryearrevenue_m_twdscope1_tco2escope2_tco2e
C001Alpha Tech Co.Technology2024500012003400
C001Alpha Tech Co.Technology2025520011003300
讀懂一份 Dataset 的基本詞彙
詞彙意思在本課程資料中
Row / Observation(觀察值)一列紀錄,代表一個被觀察的單位一家公司在一個年度的資料
Column / Variable(變數)一欄,記錄同一種特性例如 year 或 energy_mwh
Dimension(維度)用來描述、分組或比較的欄位company_name、year、sector
Measure(數值欄位)可以加總、比較或計算的數值scope1_tco2e、energy_mwh、revenue_m_twd
Metric(指標)從資料定義或計算出、可以解讀的數字Scope 1+2 排放量、排放強度
Unit(單位)數值的度量方式,必須和數值一起看tCO2e、MWh、NT$ million
Scope 1、2、3:本課程只使用概念層級的定義
範圍概念本課程如何使用
Scope 1組織直接產生的排放,例如自有設備燃燒燃料使用 scope1_tco2e
Scope 2購買電力等能源所造成的間接排放使用 scope2_tco2e
Scope 3價值鏈中其他的間接排放,例如供應商與產品使用資料中有 scope3_tco2e 欄位,但本基礎課程不做完整 Scope 3 核算,也不放進核心公式

Absolute metric(絕對指標)

  • 直接看總量,例如 Scope 1+2 排放量(tCO2e)
  • 回答「一共排放了多少」
  • 會受公司規模與營運量影響

Intensity metric(強度指標)

  • 把總量除以一個基準,例如每百萬元營收的排放量
  • 回答「相對於營運規模,排放多少」
  • 分母改變時,指標也會改變,因此要同時看分子與分母
本課程使用的公式(簡化的教學範例)
Scope 1+2 emissions = scope1_tco2e + scope2_tco2e
Emissions intensity = Scope 1+2 emissions / revenue_m_twd
Unit = tCO2e per NT$ million revenue

注意

指標公式可被正確計算,不代表不同公司一定可直接比較;仍需檢查組織邊界、會計方法、單位與資料完整性。本課程的公式是簡化的教學範例,並不等同任何特定揭露準則或官方核算方法。

資訊

沒有定義與單位的數字不算證據。看到「1000」時先問:1000 什麼?是 tCO2e、MWh,還是百萬元?是哪一家公司、哪一年?
示範:同一組數字,兩種指標

延續上方示意表的數值(僅為說明,非課程檔案中的實際數值):Alpha Tech Co. 的 Scope 1+2 排放量從 2024 年的 1200+3400=4600 tCO2e,變為 2025 年的 1100+3300=4400 tCO2e,絕對排放量下降。但同一年營收從 5000 上升到 5200(百萬元),排放強度則從 4600/5000=0.92 下降到 4400/5200≈0.85(tCO2e per NT$ million revenue)。兩個指標都下降,方向一致;但下降的原因可能不同:一個只看總量,一個把營收規模也考慮進去。

  • 只關心總排放責任、法規申報或淨零目標時,通常以絕對排放量為主。
  • 想比較不同規模的公司或同一公司不同年度的營運效率時,通常需要同時看強度指標。
  • 如果只看絕對量下降就宣稱「進步」,可能忽略了營收同時下降的情況。
  • 如果只看強度指標下降就宣稱「進步」,也可能忽略了絕對排放量仍在上升。
自我檢測

某家示範公司的 Scope 1+2 排放量下降了,但同一期間營收也明顯下降。下列哪一種做法最恰當?

某家示範公司的 Scope 1+2 排放量下降了,但同一期間營收也明顯下降。下列哪一種做法最恰當?

重點: 數值、定義與單位必須一起看。

Notebook 與 pandas

35 分鐘

Notebook 與 Python 最低必要基礎

學習目標:能在 Notebook 執行基本 Python / pandas 程式碼,不要求背誦語法。

Notebook 的心智模型
元素用途
Markdown cell用文字記錄問題、假設、說明與結論,讓別人知道你為什麼這樣做
Code cell放要執行的 Python 程式碼,負責實際的分析
Output程式執行後的結果,例如表格、數字或錯誤訊息
Run order(執行順序)Notebook 會記住已執行的內容;執行順序會影響結果

資訊

執行順序很重要。可重現的 Notebook 應該能從全新的 Kernel 由上到下一次執行完成(例如使用 Restart & Run All)。如果只有「照某個特別順序手動點」才跑得出來,別人就無法重現你的結果。
最少必要的 Python:指定變數
# 用 = 把值存進變數(assignment)
company = "Alpha Tech"   # 文字(string)要加引號
year = 2025              # 數字(number)不加引號
threshold = 1000
  • Assignment(指定):用 = 把一個值存進變數,之後可以用名稱取用
  • 文字與數字:文字要加引號,例如 "Technology";數字不加,例如 2025
  • Function call(呼叫函式):名稱後面加括號,例如 pd.read_csv(...)
  • Dot notation(點號):看得懂 df.head() 是「對 df 做 head 這個動作」即可
  • Comment(註解):# 後面的文字不會被執行,用來說明這一行在做什麼
  • 讀錯誤訊息:從最後一行看起,它通常直接告訴你是哪個名稱或欄位出了問題
最少必要的 pandas:載入資料並看前幾列
import pandas as pd

# 檔案需與 Notebook 放在同一個資料夾
df = pd.read_csv("DS101_ESG_Company_Data_Clean.csv")
df.head()
讀懂一則錯誤訊息

你輸入 df["scope_1"],結果最後一行出現 KeyError: 'scope_1'。這不是電腦壞了,而是它告訴你:資料中沒有叫做 scope_1 的欄位。下一步是執行 df.columns 看實際的欄位名稱,會發現正確的名稱是 scope1_tco2e。錯誤訊息是線索,不是失敗。

  1. 逐行解釋
    請 AI 說明每一行程式碼在做什麼,而不是只給一段總結。
  2. 列出使用的欄位
    請 AI 列出程式碼用到哪些欄位,再和 df.columns 或資料字典比對。
  3. 說明預期輸出
    請 AI 說明執行後應該得到幾列、幾欄或什麼樣子的結果,再用實際輸出核對。
  4. 不可捏造欄位
    要求 AI 只使用資料中真正存在的欄位;看到不認識的欄位名稱時,先查資料字典再使用。

注意

使用 AI 工具時,只貼課程提供的模擬資料或欄位名稱。未經授權,不要上傳機構或公司的機密資料,也不要在公開或共用的 Prompt 中放入個人資料或敏感資料。AI 的解釋可以幫助理解,但它本身不是證據:程式能執行,也不代表分析一定正確。
常見錯誤訊息一覽(先看最後一行)
錯誤訊息通常代表什麼先檢查什麼
NameError用到一個還不存在的名稱建立這個變數的 cell 是否已經執行過
KeyError欄位名稱在資料中不存在df.columns 的實際拼法與大小寫
SyntaxError程式碼的括號、引號或縮排不完整是否少了一個括號或引號,通常就在報錯那一行附近
TypeError對不相容的資料型態做了某個操作,例如把文字和數字相加該欄位的資料型態(df.dtypes)是否符合預期
  • 這個 cell 用到的名稱,是不是都已經在前面的 cell 建立過?
  • 如果是重新打開舊的 Notebook,有沒有先用 Restart & Run All 重新跑過一次?
  • 複製貼上別人的程式碼時,欄位名稱是否和自己的資料一致,而不是對方範例資料的欄位?
自我檢測

你打開 Notebook 後直接執行含有 df.head() 的 cell,出現 NameError: name 'df' is not defined。最恰當的處理方式是什麼?

你打開 Notebook 後直接執行含有 df.head() 的 cell,出現 NameError: name 'df' is not defined。最恰當的處理方式是什麼?

重點: 本課程不是測你能否背 Python,而是測你能否理解分析流程並驗證結果。

40 分鐘

用 pandas 檢查、選取與篩選資料

學習目標:能使用 pandas 回答「資料長什麼樣、有哪些欄位、哪些列符合條件」。

檢查資料的五個基本指令
df.head()
df.shape
df.columns
df.info()
df.describe()
每個指令回答什麼問題
指令回答的問題
df.head()前五列長什麼樣子?欄位名稱和數值看起來合理嗎?
df.shape一共有幾列、幾欄?(輸出為 (列數, 欄數))
df.columns有哪些欄位?名稱怎麼拼?
df.info()每個欄位是什麼資料型態?有沒有缺失值?
df.describe()數值欄位的最小值、最大值、平均值等摘要,有沒有令人意外的數字?
選取欄位(注意是兩層方括號)
df[["company_name", "year", "scope1_tco2e", "scope2_tco2e"]]
篩選列:只留下 2025 年
df[df["year"] == 2025]
多個條件:2023 年以後且產業為 Technology
df[(df["year"] >= 2023) & (df["sector"] == "Technology")]

資訊

三個容易出錯的地方:比較相等要用兩個等號 ==(一個 = 是指定變數);多個條件之間用 &,而且每個條件都要加上小括號;文字要完全相符,"technology" 和 "Technology" 在 pandas 中是不同的值。
排序:依 Scope 1 排放量由高到低
df.sort_values("scope1_tco2e", ascending=False)
  • 列數:結果剩下幾列?和你預期的一樣嗎?
  • 欄位:選到的是不是你要的欄位?有沒有漏掉或多出?
  • 篩選條件:條件寫的真的是你想問的嗎(年份、產業、大於或大於等於)?
  • 空的結果:出現 0 列時,先檢查拼字、大小寫與資料型態,不要直接下結論說「沒有資料」
  • 令人意外的最大值或最小值:先確認單位與定義,再判斷是否需要查證
每一步都要說得出來的三件事
  1. 輸入是什麼:例如完整的 df,共 24 列
  2. 做了什麼:例如只保留 year 為 2025 的列
  3. 輸出剩下什麼:例如 4 列,每家公司一列

注意

程式能執行,不代表分析正確。df[df["sector"] == "technology"] 不會報錯,但會得到 0 列,因為資料中的值是 "Technology"。如果你沒有檢查列數,就可能誤以為「這個產業沒有資料」。
  • df["sector"].unique():列出這個欄位出現過哪些不重複的值,常用來檢查拼法是否一致
  • df["sector"].value_counts():計算每個值出現的次數,適合快速了解類別分布
  • df["sector"].nunique():有幾種不重複的值,不需要把每一個都列出來時使用
  • df.isna().sum():每個欄位各有幾個缺失值,篩選前先確認這點,結果才不會少算
示範:輸入、做了什麼、輸出剩下什麼

輸入:完整的 df,共 24 列。做了什麼:df[df["company_name"] == "Harbor Foods Co."].sort_values("year"),先篩選出 Harbor Foods Co. 的列,再依年度排序。輸出剩下什麼:預期剩下 6 列(2020 至 2025 各一列),且 year 欄位應該由小到大排列;如果列數不是 6,代表公司名稱拼法可能不一致,需要先用 df["company_name"].unique() 核對。

自我檢測

下列哪一個 pandas 寫法可以篩選出 year 為 2025 的列?

下列哪一個 pandas 寫法可以篩選出 year 為 2025 的列?

重點: 每一步分析都要能說明「輸入是什麼、做了什麼、輸出剩下什麼」。

Guided Lab

45 分鐘

Guided Lab:第一次 ESG 資料分析

學習目標:在教師引導下,用 clean dataset 完成一份可重現的小型分析,並把觀察分成事實、解讀與待查證。

資訊

Lab 問題:2021–2025 年,四家示範公司的 Scope 1 + 2 排放量與排放強度如何變化?哪些觀察值得進一步查證?
  1. 載入資料
    載入 DS101_ESG_Company_Data_Clean.csv。
  2. 檢查資料
    檢查 shape、columns、資料型態與前幾列。
  3. 確認單位
    從資料字典確認 revenue_m_twd、scope1_tco2e 與 scope2_tco2e 的單位。
  4. 建立 Scope 1+2 欄位
    建立 scope12_tco2e = scope1_tco2e + scope2_tco2e。
  5. 建立排放強度欄位
    建立 scope12_intensity = scope12_tco2e / revenue_m_twd,單位是 tCO2e per NT$ million revenue。
  6. 篩選年度
    只保留 2021 至 2025 年的資料,並檢查列數。
  7. 排序一個年度
    選一個年度,依排放強度排序,並寫下這只是單一年度的比較。
  8. 依公司整理年度數值
    依公司與年度分組,保留 year 這個維度,不要把所有年度壓成一個數字。
  9. 記錄三個觀察
    用自己的話寫下三個從輸出看到的觀察。
  10. 標示證據類型
    為每個觀察標示:Fact from data(資料事實)、Interpretation(解讀)或 Needs verification(待查證)。
  11. 寫一句限制
    寫下一句說明這份分析做不到什麼的限制說明。
步驟 1 至 5:載入、檢查並建立兩個衍生欄位
import pandas as pd

df = pd.read_csv("DS101_ESG_Company_Data_Clean.csv")
df.shape
df.info()
df.head()

# 衍生欄位:Scope 1+2 排放量(tCO2e)
df["scope12_tco2e"] = df["scope1_tco2e"] + df["scope2_tco2e"]

# 衍生欄位:排放強度(tCO2e per NT$ million revenue)
df["scope12_intensity"] = df["scope12_tco2e"] / df["revenue_m_twd"]
步驟 6 至 8:篩選、排序與依公司整理年度數值
# 步驟 6:只保留 2021 至 2025 年
df_lab = df[(df["year"] >= 2021) & (df["year"] <= 2025)]
df_lab.shape  # 預期 20 列:4 家公司 x 5 個年度

# 步驟 7:選一個年度,依排放強度排序
df_lab[df_lab["year"] == 2025].sort_values("scope12_intensity", ascending=False)[["company_name", "year", "scope12_intensity"]]

# 步驟 8:依公司與年度分組,保留 year 維度
annual = (
    df_lab.groupby(["company_name", "year"])[["scope12_tco2e", "revenue_m_twd"]]
    .sum()
    .reset_index()
)
# 強度用加總後的分子除以分母重新計算,不要直接加總強度
annual["scope12_intensity"] = annual["scope12_tco2e"] / annual["revenue_m_twd"]
annual
為每個觀察標示證據類型(句型範例,請填入你自己的輸出)
標籤意思句型範例
Fact from data(資料事實)直接從輸出讀到、可以被別人重現的數字在本模擬資料中,[公司] 的 scope12_tco2e 從 2021 年的 [數值] 變為 2025 年的 [數值](單位:tCO2e)。
Interpretation(解讀)你根據事實提出的看法,要說明依據與不確定性[公司] 的排放強度下降幅度大於絕對排放量,可能部分反映營收增加,而不一定代表排放效率改善。
Needs verification(待查證)資料本身無法確認,需要其他資料或詢問資料提供者[公司] 在 [年份] 的變化特別明顯,需要確認組織邊界或計算方法是否在該年有所調整。
  • 一份可以從上到下重新執行的 Notebook
  • 兩個衍生欄位:scope12_tco2e 與 scope12_intensity
  • 至少三個標示清楚的證據陳述(事實、解讀或待查證)
  • 至少一句限制說明
  • 沒有資料無法支持的因果說法

注意

這份資料只能描述「發生了什麼變化」,不能單獨證明「為什麼」。請避免寫出「因為導入再生能源,所以排放下降」這類因果說法,也不要把結果當成公司排名或投資建議。限制說明範例:「本分析使用模擬的教學資料,公式為簡化版本,未檢查各公司的組織邊界與計算方法是否一致,因此不同公司之間的比較僅供練習。」

完成

如果你用 AI 協助寫或解釋這些程式碼,請逐項確認:欄位名稱存在、公式與課程定義一致、單位正確、列數符合預期。AI 可以協助分析;驗證與結論的責任在你。
這個 Lab 中常見的疏漏(可用來自我檢查)
疏漏為什麼會造成錯誤怎麼避免
分組後直接把 scope12_intensity 加總或平均強度是一個比率,直接加總或平均會讓分母失真先把分子與分母分別加總,重新相除後才得到正確的強度
只看一個年度就排名所有公司單一年度可能受當年特殊事件影響,不代表長期表現至少看完整個 2021–2025 的範圍,再描述趨勢
把排放強度下降直接寫成「公司變好了」強度下降可能只是營收上升,分母變大同時引用絕對排放量,並在限制中說明無法確定原因

重點: 一份好的分析不只產生數字,也保留公式、單位、證據與限制。

接下來做什麼?