🗺️ AI 學習與考證地圖
中級科目二程式實戰 · 缺值處理與型別

缺值逼整數變浮點:
median 補洞、Int64 復籍

五行程式、三個考點。 None 放進整數清單的瞬間,整欄被默默升格成 float64(本站 pandas 3.0.2 實跑:[2022.0, nan, 2024.0])。 median() 預設跳過缺值、只看 [2022, 2024]——偶數筆取中間兩個的平均 = 2023.0(2023 根本不在原始資料裡)。 astype('Int64') 大寫 I 是 pandas 可空整數——print 實跑輸出逐字是 [2022, 2023, 2024] 與 Int64(答案 A)。加映:小寫 i 的 astype('int64') 見 NaN 直接 IntCastingNaNError——報錯訊息還推薦你用 'Int64'。

閱讀模式

00題目

執行下列程式後,year 欄位的值與資料型態判讀何者正確?

import pandas as pd   # 帶 pandas 進場,慣例縮寫 pd

df = pd.DataFrame({'year': [2022, None, 2024]})   # 三筆年份,中間破一個洞
df['year'] = df['year'].fillna(df['year'].median()).astype('Int64')   # 中位數補洞 → 轉可空整數
print(df['year'].tolist())   # 印出值清單
print(df['year'].dtype)      # 印出資料型態

先說:點名簿的空格與兩種筆

想像一本全班的座號名簿:座號本來都是整數。有一格沒填——為了記住「這格是空的」,pandas 把整欄換成「可以寫小數的鉛筆」(float64)來寫,因為它的字典裡「空格」(NaN)是浮點世界的公民,整數格式容不下它。這就是實跑看到的第一幕:[2022, None, 2024] 進表後變成 [2022.0, nan, 2024.0]——你沒叫它變,它默默升格了。

補洞用的是中位數:把洞跳過、剩 [2022, 2024] 排排站,偶數筆就取中間兩個的平均——2023.0。補完想改回整數,有兩種筆:小寫 i 的 int64 是老派原子筆——格式乾淨但一格空白都不准(見 NaN 直接報錯);大寫 I 的 Int64 是新款鋼筆——整數格式、還能保留空格(<NA>)。本題先補了洞再轉,所以兩種筆都行;但考卷寫的是大 I,輸出就是可空整數 Int64。

三個先立好的事實(全部實跑): None 進數值表即變 nan、整欄升格 float64——「整數混缺值」的預設世界是浮點,不是 object。 median() 預設 skipna——跳洞計算、回傳 float(不是字串)。 大 I 小 i 之差:'Int64' 能裝 <NA>'int64' 見 NaN 就丟 IntCastingNaNError——報錯訊息還親自推薦你 e.g. 'Int64'。

先點開看:默默升格Int64 大寫 IIntCastingNaNError

不熟 pandas 名詞?你需要先認識下列名詞

點擊後出現漸進式說明:白話說明 → 說清楚一點 → 常見錯誤與考點。

缺值的真面目
NaN 是什麼None vs NaN默默升格float64
中位數補洞
median 中位數skipna 跳洞偶數筆的中位數fillna 補洞補值策略
可空整數
astype 轉型Int64 大寫 Iint64 小寫 ipd.NAIntCastingNaNError
dtype 世界觀
dtype 是什麼extension 家族object 雜物櫃補值與洩漏

不熟 Python?你需要先認識下列名詞

點擊後出現漸進式說明

建表與選欄
import pandas as pd字典建表Series 是什麼df['year'] 選欄
回寫與鏈
= 回寫同欄點點接龍'Int64' 字串參數
輸出判讀
tolist() 變清單print 兩行輸出.0 的名牌
選項法醫室
median 回傳什麼bool 怎麼來

01逐行拆解:一個洞、三站補救

五段,一段一段走完。右上角的「看位置」可以把這一段放回完整程式裡看。

第 1 行帶 pandas 進場
import pandas as pd   # 資料表工具箱,慣例縮寫 pd

pandas 是 Python 的資料表工具箱,慣例縮寫 pd(跟 numpy 的 np、seaborn 的 sns 同一種暗號)。本題的主角們——DataFrame、fillna、median、astype——全住在這箱子裡。

相關名詞:import pandas as pd

第 2 行建表:None 進場,整欄默默升格
df = pd.DataFrame({'year': [2022, None, 2024]})   # 字典建表:鍵當欄名、清單當欄值

字典建表:鍵 'year' 當欄名、清單當欄值。重點在 None——缺值進了數值欄,會被換成 NaN;而 NaN 是浮點世界的公民,整數格式容不下它,所以整欄被升格成 float64。實跑證據:這行跑完 dtype 已是 float64、值是 [2022.0, nan, 2024.0]——注意 2022 悄悄長出了 .0 的名牌。

「不報錯的錯」家族又一員:沒有任何警告、沒有任何錯誤——整數欄就這樣變了浮點欄。考題最愛考這個瞬間:int + None = float64,不是 object、更不是 int。

相關名詞:字典建表None vs NaN默默升格

第 3 行補洞轉型:median → fillna → astype 三站
df['year'] = df['year'].fillna(df['year'].median()).astype('Int64')   # 三站流水線+回寫

一行三站,從最裡面讀出來:站 1 median()——預設跳過缺值,只看 [2022, 2024],偶數筆取中間兩個的平均 = 2023.0(實跑 type 是 float64,不是字串——D 的死因)。站 2 fillna(2023.0)——把洞補上:[2022.0, 2023.0, 2024.0],此刻仍是 float64站 3 astype('Int64')——轉成大寫 I 的 pandas 可空整數。最後 df['year'] = 把成品回寫同一欄。

相關名詞:median 中位數fillna 補洞astype 轉型= 回寫同欄點點接龍

第 4 行print(tolist()):值的驗收
print(df['year'].tolist())   # Series → Python 清單再印出

tolist() 把 Series 變回普通 Python 清單。實跑輸出:[2022, 2023, 2024]——乾淨整數、沒有 .0(Int64 的元素 tolist 後是 Python int)。三個值都對得上:2022 與 2024 原班人馬、2023 是 median 補進來的。

相關名詞:tolist() 變清單.0 的名牌

第 5 行print(dtype):型態的驗收
print(df['year'].dtype)   # 印出資料型態——第二行證據

實跑輸出:Int64——大寫 I,pandas 的可空整數(nullable integer)。兩行輸出跟選項 A 逐字吻合:[2022, 2023, 2024] + Int64。大小寫在這裡是身分證:int64(小 i)是 numpy 整數、Int64(大 I)是 pandas 擴充型態——只有後者裝得下 <NA>。

一句話記住本題:缺值逼整數變浮點;median 補洞、Int64 復籍——大 I 能裝 NA、小 i 見 NaN 就炸。選項 A 的每個字都在這五行裡。

相關名詞:dtype 是什麼Int64 大寫 Iint64 小寫 iprint 兩行輸出

02缺值升格觀察站:None 進場的瞬間

同一份三筆年份,換三種裝法——dtype 會走到哪裡去?(pandas 3.0.2 全部實跑):

互動實驗室:缺值升格觀察站int64 / float64 / object——誰把整數變了浮點
本站實跑判決:無洞的三個整數 → int64 安然無恙;塞進一個 None → 整欄升格 float64、None 變 nan、2022 長出 .0。B 選項夢想的 object 世界要手動 dtype=object 才做得出來——預設推斷根本不走那條路。「整數混缺值」的預設歸宿是浮點——這是 pandas 的地基設定,不是 bug。

相關名詞:默默升格NaN 是什麼object 雜物櫃

03中位數拆解:跳洞、排隊、取中間

median() 在這份資料上到底怎麼算?三個視角實跑:

互動實驗室:中位數拆解skipna 預設跳洞——偶數筆取中間兩個的平均
本站實跑判決:預設 skipna——洞先跳過、只剩 [2022, 2024] 兩筆;偶數筆的中位數=中間兩個的平均 (2022+2024)/2 = 2023.0。注意兩件事: 2023 根本不在原始資料裡——中位數可以是「無中生有的合理值」; 回傳的 type 實跑是 numpy.float64——數值欄的 median 回傳數值,「必定回傳字串」(D)兩頭落空:就算硬對字串欄呼叫,pandas 3 直接 TypeError「Cannot perform reduction 'median' with string dtype」。

相關名詞:skipna 跳洞偶數筆的中位數median 回傳什麼

04大 I 小 i 對決:一個字母的生死線

如果不先 fillna、直接轉整數呢?大小寫各跑一遍:

互動實驗室:大 I 小 i 對決Int64 能裝 NA、int64 見 NaN 就炸——實跑對照
報錯訊息親自劃重點(實跑全文):IntCastingNaNError: Cannot convert non-finite values (NA or inf) to integer. Replace or remove non-finite values or cast to an integer type that supports these values (e.g. 'Int64')——pandas 自己告訴你:要嘛先補洞(Replace)、要嘛用大 I('Int64')。本題兩件都做了:先 fillna 再轉大 I——雙保險,穩穩落地。

相關名詞:IntCastingNaNErrorpd.NAextension 家族

05三站流水線追蹤器:值與 dtype 逐站驗收

把第 3 行拆成四個時刻,每一站看兩件事:值長什麼樣、dtype 是誰

互動實驗室:三站流水線追蹤器原始 → median → fillna → astype——逐站實跑
這一站的值
這一站的 dtype
驗收口訣:浮點進場(float64)→ 算出 2023.0(float 純量)→ 補洞仍浮點(float64)→ 大 I 收尾(Int64)。dtype 只在最後一站改變——fillna 不改型態、astype 才改型態,兩個方法各司其職。

相關名詞:fillna 補洞astype 轉型Series 是什麼

06考場加碼:dtype 速查表與 SimpleImputer 對照

缺值 × 型別的兩張必備小抄:

dtype寫法能裝缺值嗎缺值長相
int64(numpy 小 i)astype('int64') / astype(int)×(IntCastingNaNError)
Int64(pandas 大 I)astype('Int64')<NA>
float64預設推斷(缺值的預設歸宿)NaN
object手動 dtype=objectNone 原樣保留
boolean(大寫家族)astype('boolean')○(bool 小寫則×)<NA>
# 第 14 頁的同一招:sklearn 方言(實跑同補 2023.0)
from sklearn.impute import SimpleImputer   # 補值器
imp = SimpleImputer(strategy='median')      # 策略:中位數——跟 fillna(median) 同心
imp.fit_transform(df[['year']])             # 實跑 → [[2022.], [2023.], [2024.]]
串起系列:本頁的 fillna(df['year'].median()) 就是第 14 頁 SimpleImputer(strategy='median') 的 pandas 方言——實跑同樣補進 2023.0。差別在紀律:正規 ML 流程的 median 要在「訓練集」上算(第 15 頁的洩漏防線——統計量只能來自訓練資料);本題是單表資料清理,全欄算 median 沒問題。median 本人已是系列三朝元老:第 13 頁(describe 三兄弟)、第 20 頁(Spark approxQuantile)、本頁(fillna 的填料)——偏態與缺值場景,中位數永遠是第一人選

相關名詞:補值策略補值與洩漏float64

07四個選項收工

A[2022, 2023, 2024],dtype 為 pandas 可空整數 Int64正確

三站實跑背書:median() 跳洞算出 2023.0(偶數筆取中間兩個平均);fillna 補洞 → [2022.0, 2023.0, 2024.0];astype('Int64') 收尾——print 實跑輸出逐字是 [2022, 2023, 2024] 與 Int64。大寫 I 的「可空整數」描述也精準:它是 pandas 擴充型態、裝得下 <NA>。

B[2022.0, None, 2024.0],dtype 仍為 object拼裝車

兩個矛盾: 預設推斷是 float64 不是 object(實跑)——object 要手動 dtype=object 才會出現; None 進數值表的瞬間就變 nan——「2022.0 長了浮點名牌」卻配「原裝的 None」是兩個世界的零件拼在一起。而且程式明明跑了 fillna——洞已經補掉,None 不可能還在。

C[2022, 0, 2024],dtype 為 bool零件全來自別的程式

0 是 fillna(0) 的結果——本題補的是 median()=2023,不是 0(實跑 fillna(0) 世界:[2022, 0, 2024]);bool 只在 astype(bool) 出現——實跑 [2022, 0, 2024] 轉 bool 得 [True, False, True](0 變 False)。兩個零件都不在本題程式裡——而且「值是整數清單、dtype 卻是 bool」本身就自相矛盾。

Dmedian() 必定回傳字串,因此 astype('Int64') 會失敗兩頭落空

實跑 type(df['year'].median())numpy.float64——數值欄的 median 回傳數值,不是字串。就算硬對字串欄呼叫 median,pandas 3 直接丟 TypeError「Cannot perform reduction 'median' with string dtype」——連「回傳字串」的機會都沒有。整條程式實跑一路綠燈,astype('Int64') 順利執行。

回到題目:現在再作答一次

再看一次同一段程式。這次你手上有一句口訣了:缺值逼整數變浮點;median 補洞、Int64 復籍

df = pd.DataFrame({'year': [2022, None, 2024]})   # None 進場 → 整欄升格 float64
df['year'] = df['year'].fillna(df['year'].median()).astype('Int64')   # 2023.0 補洞 → 大 I 收尾

08自我檢測

八題,全部都是本題的延伸。答錯會直接告訴你錯在哪。

09重點整理

  1. 五行程式三個考點:None 進表整欄升格 float64;median 跳洞算 2023.0 補回;astype('Int64') 轉可空整數——print 出 [2022, 2023, 2024] 與 Int64。
  2. 正確答案 A:[2022, 2023, 2024]、dtype 為 pandas 可空整數 Int64——print 實跑輸出逐字吻合。
  3. 升格鐵則(實跑):int + None 建表 → dtype float64、值 [2022.0, nan, 2024.0]——NaN 是浮點公民,整數容不下它;不是 object、更不會報錯。
  4. median 的算法(實跑):預設 skipna 跳洞、只看 [2022, 2024];偶數筆取中間兩個的平均 = 2023.0——一個「不在原始資料裡」的無中生有合理值。
  5. fillna 不改型態:補完洞仍是 float64——astype 才改型態;兩個方法各司其職(三站流水線追蹤器逐站驗收)。
  6. 大 I 小 i 生死線(實跑):'Int64' 能裝 <NA>(不 fillna 直接轉也合法:[2022, <NA>, 2024]);'int64' 見 NaN 直接 IntCastingNaNError
  7. 報錯訊息劃重點:IntCastingNaNError 的原文建議「Replace or remove non-finite values or cast to … (e.g. 'Int64')」——pandas 親自告訴你兩條活路,本題兩條都走了。
  8. B 的死因(實跑):預設推斷是 float64 不是 object;None 進表即變 nan——「2022.0 配 None」是拼裝車;且 fillna 已把洞補掉。
  9. C 的死因(實跑):0 來自 fillna(0)、bool 來自 astype(bool)([True, False, True])——兩個零件都不在本題程式裡。
  10. D 的死因(實跑):type(median()) 是 numpy.float64——不是字串;字串欄的 median 在 pandas 3 直接 TypeError——「必定回傳字串」兩頭落空。
  11. 系列呼應:fillna(median) ≡ 第 14 頁 SimpleImputer(strategy='median')(實跑同補 2023.0);正規 ML 流程 median 要在訓練集上算(第 15 頁洩漏防線)。
  12. 考場口訣缺值逼整數變浮點;median 補洞、Int64 復籍——大 I 能裝 NA、小 i 見 NaN 就炸
完整程式碼