Pandas apply
apply() 是 Pandas 中非常強大的方法,可以對 DataFrame 或 Series 的每個元素、每一列或每一欄套用自訂函數。
對 Series 使用 apply()
對 Series 的每個元素套用函數:
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
# 每個元素平方
result = s.apply(lambda x: x ** 2)
print(result)
0 1
1 4
2 9
3 16
4 25
dtype: int64
使用自訂函數
def categorize(value):
if value < 3:
return 'low'
elif value < 5:
return 'medium'
else:
return 'high'
result = s.apply(categorize)
print(result)
0 low
1 low
2 medium
3 medium
4 high
dtype: object
對 DataFrame 使用 apply()
對每一欄套用(axis=0,預設)
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
# 計算每欄的總和
result = df.apply(sum)
print(result)
A 6
B 15
C 24
dtype: int64
對每一列套用(axis=1)
# 計算每列的總和
result = df.apply(sum, axis=1)
print(result)
0 12
1 15
2 18
dtype: int64
套用自訂函數
# 對每欄計算範圍(最大值 - 最小值)
result = df.apply(lambda col: col.max() - col.min())
print(result)
A 2
B 2
C 2
dtype: int64
# 對每列計算
def row_info(row):
return f"A={row['A']}, B={row['B']}, sum={row['A'] + row['B']}"
result = df.apply(row_info, axis=1)
print(result)
傳入額外參數
def multiply(x, n):
return x * n
# 使用 args 傳入額外參數
result = s.apply(multiply, args=(10,))
print(result)
0 10
1 20
2 30
3 40
4 50
dtype: int64
或使用 lambda:
result = s.apply(lambda x: multiply(x, 10))
applymap():對每個元素套用
對 DataFrame 的每一個元素套用函數:
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 每個元素平方
result = df.applymap(lambda x: x ** 2)
# 或在較新版本使用 map
result = df.map(lambda x: x ** 2)
print(result)
A B
0 1 16
1 4 25
2 9 36
apply() vs 向量化運算
向量化運算通常比 apply() 更快:
import numpy as np
df = pd.DataFrame({
'A': range(10000),
'B': range(10000)
})
# 較慢:使用 apply
df['C'] = df.apply(lambda row: row['A'] + row['B'], axis=1)
# 較快:向量化運算
df['C'] = df['A'] + df['B']
# 較快:使用 NumPy
df['C'] = np.add(df['A'], df['B'])
建議:能用向量化運算就用向量化,apply() 適合複雜邏輯或無法向量化的情況。
回傳多個值
def stats(col):
return pd.Series({
'min': col.min(),
'max': col.max(),
'mean': col.mean()
})
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
result = df.apply(stats)
print(result)
A B
min 1.0 4.0
max 3.0 6.0
mean 2.0 5.0
實際應用範例
資料清理
df = pd.DataFrame({
'name': [' Alice ', 'BOB', 'charlie'],
'email': ['ALICE@TEST.COM', 'bob@test.com', 'CHARLIE@test.com']
})
# 清理 name 欄位
df['name'] = df['name'].apply(lambda x: x.strip().title())
# 清理 email 欄位
df['email'] = df['email'].apply(str.lower)
分類計算
df = pd.DataFrame({
'score': [85, 72, 93, 65, 78]
})
def grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
else:
return 'D'
df['grade'] = df['score'].apply(grade)
處理複雜資料
df = pd.DataFrame({
'data': ['{"name": "Alice"}', '{"name": "Bob"}']
})
import json
df['parsed'] = df['data'].apply(json.loads)
df['name'] = df['parsed'].apply(lambda x: x['name'])