【pandas】-1-读取数据
【pandas】-2-数据查询
【pandas】-3-Pandas 索引
【pandas】-4- 索新增列,assign,applay,map使用
【pandas】-5-缺失值处理
【pandas】-6-排序&去重
【pandas】-7-数据分组处理
【pandas】-8-数据变形/数据透视
【pandas】pandas中mask()方法的详细用法

pandas apply 方法详解


apply() 是 pandas 中非常强大和灵活的方法,用于对 DataFrame 或 Series 应用自定义函数。下面详细讲解其用法。

基本语法

DataFrame.apply()

DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)

Series.apply()

Series.apply(func, convert_dtype=True, args=(), **kwargs)

参数说明

  • func: 要应用的函数
  • axis:
    • 0 或 ‘index’: 对每列应用函数(默认)
    • 1 或 ‘columns’: 对每行应用函数
  • raw: 布尔值,决定传递的数据类型
    • False: 将每行/列作为 Series 传递
    • True: 将每行/列作为 ndarray 传递
  • result_type: 仅当 axis=1 时有效
    • ‘expand’: 将列表式结果转换为列
    • ‘reduce’: 返回 Series(如果可能)
    • ‘broadcast’: 将结果广播回原始形状

基本用法示例

1. 对 Series 应用函数

import pandas as pd
import numpy as np

# 创建 Series
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

# 应用自定义函数
def custom_func(x):
    return x * 10 if x > 3 else x

result = s.apply(custom_func)
print(result)

2. 对 DataFrame 按列应用函数

# 创建 DataFrame
df = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [10, 20, 30, 40],
    'C': [100, 200, 300, 400]
})

# 对每列求和(虽然可以直接用 df.sum())
result = df.apply(np.sum, axis=0)
print(result)
# 输出: A:10, B:100, C:1000

# 对每列应用自定义函数
def column_stats(col):
    return f"mean:{col.mean():.2f}, std:{col.std():.2f}"

result = df.apply(column_stats)
print(result)

3. 对 DataFrame 按行应用函数

# 对每行求和
result = df.apply(np.sum, axis=1)
print(result)
# 输出: 0:111, 1:222, 2:333, 3:444

# 对每行应用复杂函数
def row_operation(row):
    return row['A'] * row['B'] + row['C']

result = df.apply(row_operation, axis=1)
print(result)

高级用法

4. 使用 args 参数传递额外参数

def weighted_sum(row, weights):
    return sum(row * weights)

weights = [0.5, 0.3, 0.2]
result = df.apply(weighted_sum, axis=1, args=(weights,))
print(result)

5. 使用 result_type 控制输出格式

# 返回多列结果
def expand_func(row):
    return pd.Series({
        'sum': row.sum(),
        'mean': row.mean(),
        'max': row.max()
    })

# 使用 expand 将结果扩展为多列
result = df.apply(expand_func, axis=1, result_type='expand')
print(result)

6. 处理多个返回值的不同方式

# 返回列表
def return_list(row):
    return [row.min(), row.max(), row.mean()]

# 不同 result_type 的效果
result1 = df.apply(return_list, axis=1)  # 返回 Series of lists
result2 = df.apply(return_list, axis=1, result_type='expand')  # 扩展为 DataFrame
result3 = df.apply(return_list, axis=1, result_type='broadcast')  # 广播回原形状

print("原始 result_type:")
print(result1.head())
print("\n使用 expand:")
print(result2.head())

7. 实际应用案例

# 数据清洗示例
df_data = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
    'age': [25, 30, 35, 40],
    'salary': ['$50,000', '$60,000', '$70,000', '$80,000'],
    'email': ['alice@email.com', 'bob@email.com', 'charlie', 'david@email.com']
})

# 清洗薪资数据
def clean_salary(sal):
    if isinstance(sal, str):
        return int(sal.replace('$', '').replace(',', ''))
    return sal

# 验证邮箱格式
def validate_email(email):
    import re
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

# 应用清洗函数
df_data['salary_clean'] = df_data['salary'].apply(clean_salary)
df_data['email_valid'] = df_data['email'].apply(validate_email)

print(df_data)

性能考虑

8. 使用 raw=True 提高性能

# 对于数值运算,使用 raw=True 可以提高性能
def simple_operation(x):
    return x * 2 + 1

# 比较性能
%timeit df.apply(simple_operation, axis=1)  # 较慢
%timeit df.apply(simple_operation, axis=1, raw=True)  # 较快

9. 替代方案

对于简单操作,考虑使用向量化操作代替 apply:

# 使用 apply(较慢)
result_slow = df.apply(lambda row: row['A'] * 2 + row['B'], axis=1)

# 使用向量化操作(较快)
result_fast = df['A'] * 2 + df['B']

# 验证结果相同
print(result_slow.equals(result_fast))  # 输出: True

总结

  1. 灵活性: apply() 可以应用任何自定义函数
  2. 方向控制: 通过 axis 参数控制按行或按列应用
  3. 输出控制: 使用 result_type 控制返回数据的格式
  4. 性能优化: 对于数值运算,考虑使用 raw=True
  5. 替代方案: 对于简单操作,优先使用向量化操作

apply() 是 pandas 中非常强大的工具,但在大数据集上使用时需要注意性能问题,尽量使用向量化操作或考虑其他优化方法。

更多推荐