Pandas 值的替換
在資料處理中,經常需要將欄位中的值替換成其他值。Pandas 提供了 map()、replace() 等方法來處理。
map():映射值
map() 用於將 Series 中的每個值根據映射關係替換成新值。
使用 dict 映射
import pandas as pd
df = pd.DataFrame({
'grade': ['A', 'B', 'C', 'A', 'B']
})
# 將等級對應到分數
grade_map = {'A': 90, 'B': 80, 'C': 70}
df['score'] = df['grade'].map(grade_map)
print(df)
grade score
0 A 90
1 B 80
2 C 70
3 A 90
4 B 80
沒有對應的值會變成 NaN
df = pd.DataFrame({'grade': ['A', 'B', 'D']})
grade_map = {'A': 90, 'B': 80, 'C': 70}
df['score'] = df['grade'].map(grade_map)
# D 沒有對應,會變成 NaN
使用函數映射
df['grade_upper'] = df['grade'].map(str.lower)
# 或使用 lambda
df['grade_len'] = df['grade'].map(lambda x: len(x))
replace():取代值
replace() 更靈活,可以直接取代指定的值。
取代單一值
df = pd.DataFrame({
'status': ['active', 'inactive', 'active', 'pending']
})
# 將 inactive 取代為 disabled
df['status'] = df['status'].replace('inactive', 'disabled')
取代多個值
# 使用 dict
df['status'] = df['status'].replace({
'active': 1,
'inactive': 0,
'pending': -1
})
# 使用 list
df['status'] = df['status'].replace(
['active', 'inactive'],
['on', 'off']
)
在整個 DataFrame 取代
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [2, 3, 4]
})
# 取代所有欄位中的值
df = df.replace(2, 200)
print(df)
A B
0 1 200
1 200 3
2 3 4
使用正規表達式
df = pd.DataFrame({
'text': ['hello-world', 'foo-bar', 'test-case']
})
# 將 - 取代為空格
df['text'] = df['text'].replace('-', ' ', regex=True)
# 更複雜的正規表達式
df['text'] = df['text'].replace(r'\d+', 'NUM', regex=True)
map() vs replace() 比較
| 特性 | map() | replace() |
|---|---|---|
| 適用對象 | 只能用於 Series | Series 和 DataFrame |
| 沒有對應時 | 變成 NaN | 保持原值 |
| 正規表達式 | 不支援 | 支援 |
| 使用場景 | 完整映射 | 部分取代 |
s = pd.Series(['A', 'B', 'C'])
mapping = {'A': 1, 'B': 2}
# map:C 會變成 NaN
print(s.map(mapping)) # [1, 2, NaN]
# replace:C 保持原值
print(s.replace(mapping)) # [1, 2, 'C']
where() 和 mask()
根據條件取代值:
where():條件為 False 時取代
df = pd.DataFrame({'value': [1, 2, 3, 4, 5]})
# value <= 3 時保持原值,否則取代為 0
df['result'] = df['value'].where(df['value'] <= 3, 0)
print(df)
value result
0 1 1
1 2 2
2 3 3
3 4 0
4 5 0
mask():條件為 True 時取代
# value > 3 時取代為 0
df['result'] = df['value'].mask(df['value'] > 3, 0)
clip():限制值的範圍
df = pd.DataFrame({'value': [1, 5, 10, 15, 20]})
# 限制在 5 到 15 之間
df['clipped'] = df['value'].clip(lower=5, upper=15)
print(df)
value clipped
0 1 5
1 5 5
2 10 10
3 15 15
4 20 15
實際應用範例
編碼轉換
df = pd.DataFrame({
'gender': ['M', 'F', 'M', 'F']
})
# 轉換為數字
df['gender_code'] = df['gender'].map({'M': 0, 'F': 1})
# 或轉換為文字
df['gender_full'] = df['gender'].map({'M': 'Male', 'F': 'Female'})
處理異常值
df = pd.DataFrame({
'age': [25, 30, -5, 150, 35] # 有異常值
})
# 將不合理的年齡設為 NaN
df['age'] = df['age'].where((df['age'] > 0) & (df['age'] < 120))
清理資料
df = pd.DataFrame({
'status': ['yes', 'Yes', 'YES', 'no', 'No', 'N/A']
})
# 統一格式
df['status'] = df['status'].str.lower().replace({
'yes': True,
'no': False,
'n/a': None
})