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'])