pandas 讀 CSV 後 Year 欄位為什麼變成 float64?
一間遊戲市場研究公司正在分析全球電子遊戲銷售情況,並準備建立一份「熱銷遊戲銷售報告」。分析師取得了一份名為 vgsales.csv 的資料集,內容包含全球銷量超過 10 萬份的電子遊戲清單。研究團隊希望透過這份資料,了解不同年份、平台與地區的銷售趨勢。 分析師在載入資料後,檢視 Year 欄位的資料型態,發現它是 float64,而非一般年份常用的整數。他想了解這樣的情形為什麼會發生。請問下列哪些原因可能導致這種狀況? 原因 A:CSV 檔中 Year 欄位有缺失值(NaN),導致 Pandas 自動將整欄轉為浮點數。 原因 B:CSV 檔中的年份資料原本是字串(如 "2006"),Pandas 轉換時出錯而變成浮點數。 原因 C:Pandas 預設會將所有數值型態讀取為 float64,不論資料是否為整數。 原因 D:CSV 檔中的年份資料可能包含小數點(例如 2006.0),因此被視為浮點數。
分析師用 pandas 讀 vgsales.csv 後,發現 Year 欄位的資料型別(dtype)是 float64,不是預期的整數 int。題目把四個可能的成因(A 到 D)打包成四個組合選項,要你找出哪些原因確實可能造成這種情形。
問你:哪些原因真的可能導致 pandas 把 Year 欄位讀成 float64?
一句話總結
正確答案是 選項 B(原因 A 和原因 D):CSV 有缺失值(NaN)時 pandas 自動升成 float64,以及年份資料本身寫成小數點格式(2006.0)時也會讀成 float64。原因 B(字串轉錯)和原因 C(pandas 全預設 float64)都不符合 pandas 的實際行為。
先感受問題:年份欄位明明是整數,為什麼被讀成小數?
遊戲研究公司的分析師小凱載入了 vgsales.csv,檢查資料型別:
Name object
Platform object
Year float64 ← 為什麼不是 int64?
Genre object
Global_Sales float64
Year 欄位只有年份(2006, 2010, 2014...),理論上應該是整數。小凱知道這背後有原因,需要找出是哪些情況造成的。
關鍵是理解 pandas 的類型推斷規則:
- 整數欄位一旦混入 NaN,numpy 的 int64 無法表示 NaN,pandas 就自動把整欄升成 float64(因為 Python float 可以用 nan 表示缺失值)。
- CSV 中本身就寫 2006.0(帶小數點)時,pandas 自然讀成 float64。
這兩個原因(A 和 D)是真實成因;原因 B 和 C 是常見誤解。
逐一拆解四個原因是否成立
- 原因 A:有缺失值(NaN)→ 成立。numpy 的 int64 本來就無法存放 NaN(NaN 是浮點數概念),所以當 pandas 讀到一欄整數資料但其中有缺失值時,它必須把整欄型別提升(upcast)成 float64,才能同時存放整數值和 NaN。這是 pandas 在 Int64(可空整數)推出之前的標準行為。
- 原因 B:字串自動轉錯 → 不成立。pandas 讀 CSV 時,如果一欄全是像 "2006" 這樣的數字字串,pd.read_csv 預設會自動嘗試轉型成整數或浮點數,不會因為「原本是字串」就「出錯變成浮點數」。字串純數字能轉換成功,通常會被讀成 int64,而不是 float64。這不是 pandas 的正常行為。
- 原因 C:pandas 預設全部讀成 float64 → 不成立。pandas 不會把所有數值都讀成 float64,它會根據內容推斷型別:純整數欄位會被推斷為 int64,有浮點數的欄位才是 float64。「預設全部 float64」這個說法不符合事實。
- 原因 D:CSV 本身寫 2006.0 → 成立。如果 CSV 中年份欄位的值是 2006.0(帶小數點),pandas 的類型推斷器看到小數點就會把它讀成 float64,這是完全合理的解析行為。Excel 或舊資料系統匯出的 CSV 有時會以這種格式儲存年份。
原因 A 和 D 成立,選組合包含且僅包含 A、D 的選項
小凱確認了:
原因 B:字串轉錯 → 不成立(pandas 不會這樣)
原因 C:全預設 float64 → 不成立(pandas 不會這樣)
原因 D:CSV 本身有 2006.0 → 成立
正確答案要包含 A 和 D,而且不包含 B 和 C。四個總選項中,「原因 A、原因 D」對應選項 B。這就是選項 B 講的:原因 A、原因 D。
技術版:pandas dtype 類型推斷機制精讀
中級考試大概率會考程式碼跟公式,所以這部分你還是要學。但如果現在學起來很痛苦,可以先跳過,等讀完其他題目回頭再來。
想像一個倉庫,每個貨架只能放同一種規格的箱子。整數箱子(int64)放不了「沒有貨」的空槽,只有浮點數箱子(float64)才有一個叫做 NaN 的特殊空槽。所以只要有一格是空的,整個貨架就必須換成浮點數箱子。CSV 裡本身就有小數點的數字,一開始就是浮點數箱子。這兩種情況都讓 Year 欄位最後放在浮點數貨架(float64)上。
| 情境 | pandas 行為 |
|---|---|
| Year 欄全是整數,無缺失值 | dtype: int64 |
| Year 欄有缺失值(NaN) | dtype: float64(int64 無法存 NaN) |
| CSV 中年份寫成 2006.0 | dtype: float64(看到小數點就是 float) |
| 解決方案:可空整數型別 | dtype: Int64(大寫 I,pandas 擴充型別) |
| 強制轉整數(去除 NaN 後) | data['Year'].fillna(0).astype(int) |
- int64
- numpy 的 64 位元有符號整數,無法存放 NaN,範圍 -2⁶³ 到 2⁶³-1。
- float64
- numpy 的 64 位元浮點數,可存放 NaN(IEEE 754 標準中的特殊值),因此成為有缺失整數的預設容器。
- Int64(大寫 I)
- pandas 擴充的可空整數型別(Nullable Integer),可以同時存整數和 NaN,是 pandas 1.0 後的解決方案。
- NaN
- Not a Number,浮點數標準(IEEE 754)中定義的特殊值,pandas 用它表示缺失值。
- dtype inference
- pandas 在 read_csv 時自動推斷每欄資料型別的機制,依據欄位中的值決定最合適的 numpy dtype。
本題沒有數學公式,核心是 pandas 的型別推斷規則:
- 欄位全為整數且無 NaN → int64
- 欄位有整數且有 NaN → float64(因 int64 無法存 NaN)
- 欄位有帶小數點的值 → float64
- 欄位有文字和數字混合 → object
- 為什麼 numpy 的 int64 無法存 NaN?NaN 是什麼型別的值?
- pandas 的 Int64(大寫 I)和 numpy 的 int64(小寫 i)差別在哪?
- 讀完 CSV 後發現 Year 是 float64,如何判斷是「因為有 NaN」還是「因為 CSV 本身有小數點」?
- 如果想把 float64 的 Year 欄轉成整數且保留 NaN,應該用哪個方法?
- pandas 的 dtype inference 對效能有什麼影響?大型 CSV 該怎麼指定 dtype?
為什麼其他總選項是錯的
字面在說什麼:字串轉換出錯和「pandas 全部讀成 float64」這兩個原因導致了 float64。
為什麼不對:原因 B 不成立:pandas 讀到純數字字串時不會「出錯變成浮點數」,它有自動型別推斷機制,會嘗試轉成整數或浮點數,但不是「出錯」。原因 C 不成立:pandas 不會把所有數值都讀成 float64,整數欄無缺失時會讀成 int64。
誰會選錯:對 pandas 的自動型別推斷機制不熟悉、誤以為「字串一定會造成問題」的人,或者誤記了「pandas 預設 float」這個說法的人。
字面在說什麼:NaN、字串轉換出錯、CSV 有小數點這三個原因都導致了 float64。
為什麼不對:原因 A 和 D 確實成立,但原因 B 不成立。pandas 讀純數字字串(如 "2006")時,是正常的型別轉換,不是「出錯」。如果 CSV 中 Year 欄有 "2006" 這樣的字串,pd.read_csv 會嘗試把它轉為整數 2006,不會無緣無故變成 float64。
誰會選錯:認為「字串也可能導致浮點數問題」的人,選了多一個不必要的原因。
字面在說什麼:pandas 全部讀成 float64 和 CSV 本身有小數點,這兩個原因造成 float64。
為什麼不對:原因 D 成立,但原因 C 不成立。「pandas 預設將所有數值讀成 float64」是錯誤的說法,整數欄(無缺失值)會被讀成 int64,而且選項 D 包含 C 卻漏掉了 A(NaN 導致 upcast),答案不完整。
誰會選錯:只記得「看到 2006.0 就是 float」,但沒想到 NaN 也是重要原因的人。
同個考點下次怎麼變形
直覺:如果 Year 欄全部都是整數、無缺失值,pandas 會讀成什麼型別?
答案:int64。pandas 讀到一欄全部都是不帶小數點的整數且沒有缺失值,類型推斷結果是 int64(64 位元整數)。這是最「乾淨」的情況,不需要升類型。用 data.dtypes 可以確認。
直覺:如果一欄同時有數字字串("2006")和真正的 NaN,pandas 會讀成什麼型別?
答案:object(字串)。如果一欄混合了數字字串和真正的 NaN,pandas 讀到後整欄型別是 object,因為 NaN 在 object 欄中以 Python None 或 numpy nan 儲存。這時需要先用 pd.to_numeric(col, errors='coerce') 轉換,把字串數字轉成浮點數、無法轉的值設為 NaN,再視需要處理缺失值。
直覺:如何在 read_csv 時就指定 Year 欄為整數型別,避免被讀成 float?
答案:用 dtype 參數:pd.read_csv('vgsales.csv', dtype={'Year': 'Int64'})。注意要用大寫 'Int64'(pandas 的可空整數型別),而不是小寫 'int64'(numpy 的 int64),因為 numpy int64 無法處理 NaN,如果 CSV 有缺失值會直接報錯。Int64 允許 NaN 存在,是更安全的選擇。
直覺:除了 Year 欄,哪些欄位的型別問題最常在實際資料中遇到?
答案:ID 欄(身分證號、訂單號):原始是整數,但如果含有前導零(如 "00123")或字串格式,應該存成 object 而非 int。日期欄:pd.read_csv 預設把日期讀成 object(字串),需要用 parse_dates 參數或 pd.to_datetime() 轉成 datetime64。布林欄:True/False 可能被讀成 bool 或 object,取決於 CSV 的實際內容(True vs "True")。
直覺:載入資料後如何快速確認哪些欄位有缺失值、哪些型別不對?
答案:兩行程式碼搞定:data.dtypes 列出所有欄位的型別、data.isnull().sum() 列出每欄缺失值個數。看完這兩個輸出,就能確定哪些欄位需要補缺失值、哪些型別需要轉換。這是探索性資料分析(EDA)的標準開局步驟。
想再往下看,這 5 個
- 資料前處理(Data Preprocessing)dtype 轉換和缺失值處理是資料前處理的核心步驟,直接影響後續分析和建模的正確性。
- 資料填補(Data Imputation)Year 欄有 NaN 時,除了轉型,還需要決定缺失年份要填入什麼值,填補策略影響分析結果。
- 資料品質監控(Data Quality Monitoring)dtype 不一致是資料品質問題的常見徵兆,定期監控資料型別有助於及早發現上游資料問題。
- 資料管線(Data Pipeline)型別推斷問題在自動化資料管線中尤其危險,通常需要在管線入口強制指定 dtype 來防止靜默錯誤。
- 特徵工程(Feature Engineering)年份型別決定後續能做什麼操作,整數才能做算術差值(計算上市幾年),浮點數需要先轉換。