什麼是缺失值?

在數據分析中,缺失值(Missing Value)指的是數據集中某些行或列沒有有效值。比如一份學生成績表中,某學生的數學成績沒填,或者某公司某季度的銷售額數據丟失了。在 pandas 中,缺失值通常用 NaN(Not a Number)表示,有時也會遇到 None,但 NaN 是更標準的數值型缺失值表示。

如何檢查缺失值?

在處理缺失值前,第一步是找到數據中哪裏有缺失值。pandas 提供了兩個簡單實用的方法:

1. isnull():標記缺失值

df.isnull() 會返回一個布爾型 DataFrame,True 表示該位置是缺失值,False 表示有效數據。

import pandas as pd
import numpy as np

# 創建一個帶缺失值的示例 DataFrame
data = {
    '姓名': ['小明', '小紅', '小剛', '小麗', '小強'],
    '年齡': [20, np.nan, 22, 21, np.nan],
    '成績': [85, 92, np.nan, 78, 88]
}
df = pd.DataFrame(data)

# 檢查所有位置是否缺失
print(df.isnull())

輸出結果:

    姓名    年齡   成績
0  False  False  False
1  False   True  False
2  False  False   True
3  False  False  False
4  False   True  False

2. isnull().sum():統計缺失值數量

df.isnull().sum() 可以快速統計每列的缺失值總數,方便定位問題。

# 統計每列缺失值數量
print(df.isnull().sum())

輸出結果:

姓名    0
年齡    2
成績    1
dtype: int64

3. info():查看數據整體缺失情況

df.info() 可以查看每列的數據類型和非空值數量,直觀判斷缺失值分佈。

df.info()

輸出結果:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   姓名      5 non-null      object 
 1   年齡      3 non-null      float64
 2   成績      4 non-null      float64
dtypes: float64(2), object(1)
memory usage: 240.0+ bytes

缺失值處理方法

處理缺失值的核心思路是:要麼刪除缺失值,要麼用合理的值填充缺失值

方法一:刪除缺失值(dropna)

當缺失值很少且不影響整體數據時,可以直接刪除包含缺失值的行或列。

1. 刪除有缺失值的行(默認)

df.dropna(axis=0, how='any')
- axis=0:刪除行(默認);axis=1:刪除列。
- how='any':只要行/列中有一個缺失值就刪除;how='all':僅當所有值都是缺失值時才刪除。

# 刪除所有有缺失值的行
df_drop_rows = df.dropna(axis=0)
print(df_drop_rows)

輸出結果(僅保留無缺失值的行):

    姓名   年齡   成績
0  小明  20.0  85.0
3  小麗  21.0  78.0

2. 刪除有缺失值的列

# 刪除所有有缺失值的列
df_drop_cols = df.dropna(axis=1)
print(df_drop_cols)

輸出結果(僅保留無缺失值的列):

    姓名
0  小明
1  小紅
2  小剛
3  小麗
4  小強

方法二:填充缺失值(fillna)

當缺失值較多或刪除會丟失關鍵信息時,填充缺失值更常用。pandas 的 fillna() 支持多種填充方式。

1. 用固定值填充

直接用某個固定值(如 0、-1)填充所有缺失值。

# 用 0 填充所有缺失值
df_fill_0 = df.fillna(0)
print(df_fill_0)

輸出結果:

    姓名    年齡   成績
0  小明  20.0  85.0
1  小紅   0.0  92.0
2  小剛  22.0   0.0
3  小麗  21.0  78.0
4  小強   0.0  88.0

2. 用統計量填充(均值/中位數/衆數)

數值型數據適合用統計量填充,比如:
- 均值:適合對稱分佈數據(如正態分佈)。
- 中位數:適合偏態分佈數據(抗極端值能力強)。
- 衆數:適合分類數據(出現次數最多的值)。

# 用年齡列的均值填充年齡缺失值
df['年齡'] = df['年齡'].fillna(df['年齡'].mean())
print(df['年齡'])

輸出結果(年齡列均值爲 (20+22+21)/3=21):

0    20.0
1    21.0
2    22.0
3    21.0
4    21.0
Name: 年齡, dtype: float64

3. 向前/向後填充(ffill/bfill)

適用於時間序列數據或有順序的數據(如按時間排列的銷售額)。
- ffill():用前一個非缺失值填充後面的缺失值。
- bfill():用後一個非缺失值填充前面的缺失值。

# 模擬時間序列數據
df_time = pd.DataFrame({'value': [1, np.nan, 3, np.nan, 5]})

# 向前填充
df_forward = df_time.fillna(method='ffill')
print("向前填充結果:")
print(df_forward)

# 向後填充
df_backward = df_time.fillna(method='bfill')
print("\n向後填充結果:")
print(df_backward)

輸出結果:

向前填充結果:
   value
0    1.0
1    1.0
2    3.0
3    3.0
4    5.0

向後填充結果:
   value
0    1.0
1    3.0
2    3.0
3    5.0
4    5.0

綜合實踐案例

假設我們有一份電商訂單數據,需要處理缺失值。

數據準備

# 訂單數據
orders = {
    '訂單ID': [101, 102, 103, 104, 105],
    '客戶姓名': ['A', 'B', 'C', 'D', 'E'],
    '金額': [150, np.nan, 200, np.nan, 80],
    '支付方式': ['微信', '支付寶', np.nan, '微信', '支付寶']
}
df_orders = pd.DataFrame(orders)

步驟1:檢查缺失值

print(df_orders.isnull().sum())

輸出:

訂單ID      0
客戶姓名     0
金額       2
支付方式     1
dtype: int64

步驟2:處理缺失值

  • 金額列:數值型,用均值填充。
  • 支付方式列:分類型,用衆數(出現次數最多的值)填充。
# 填充金額列的缺失值(均值)
df_orders['金額'] = df_orders['金額'].fillna(df_orders['金額'].mean())

# 填充支付方式列的缺失值(衆數)
df_orders['支付方式'] = df_orders['支付方式'].fillna(df_orders['支付方式'].mode()[0])

print(df_orders)

輸出結果:

   訂單ID 客戶姓名     金額 支付方式
0   101    A  150.0   微信
1   102    B  143.333333   支付寶  # 均值=(150+200+80)/3≈143.33
2   103    C  200.0   支付寶  # 衆數是支付寶(出現2次)
3   104    D  143.333333   微信
4   105    E   80.0   支付寶

總結

缺失值處理的核心步驟:
1. 檢查缺失值:用 isnull()isnull().sum() 定位問題。
2. 選擇處理策略
- 缺失值極少(<5%)且不重要 → 刪除dropna())。
- 缺失值較多或關鍵數據 → 填充fillna()),優先用統計量(均值/中位數)或固定值。
3. 驗證結果:處理後再次檢查數據,確保缺失值已合理處理。

處理缺失值沒有“萬能方法”,需結合數據特點和業務需求靈活選擇,避免因處理不當導致數據偏差。

小夜