Python案例如何用Pandas做数据Apply函数

wen python案例 1

Python案例实战:如何用Pandas做数据Apply函数——从入门到高级场景全解析

📖 目录导读

  1. Apply函数是什么?为什么它是Pandas的“瑞士军刀”?
  2. Apply基础用法:对Series和DataFrame进行逐元素/逐行/逐列操作
  3. 自定义函数与Lambda:让数据处理更灵活
  4. 实战案例:数据清洗、特征工程与条件计算
  5. 性能对比:Apply vs 向量化 vs Iterrows vs Map
  6. 高级技巧:Axis参数、Args传递、避免陷阱
  7. 常见问题Q&A:面试真题与避坑指南

Apply函数是什么?为什么它是Pandas的“瑞士军刀”?

在Python数据处理中,Pandas的apply()函数可能是最容易被低估却又最强大的工具之一。apply()允许你对DataFrame或Series的每个元素、每一行或每一列,应用一个自定义函数。

Python案例如何用Pandas做数据Apply函数

核心价值:当你需要执行标准运算符(如、、mean())无法直接完成的逻辑时,apply()就是你的救星,对某列数据根据复杂规则打标签、结合多列数据计算新特征、或者对字符串进行模式匹配。

:apply和Python内置的map函数有什么区别?
pandas.Series.map()仅适用于Series,且要求映射关系是字典或单一函数,而apply()更通用,能操作DataFrame的轴向(行或列),并且支持传入带参数的函数,简单说:map()是“一维映射”,apply()是“多维逻辑引擎”。


Apply基础用法:对Series和DataFrame进行逐元素/逐行/逐列操作

1 对Series应用函数(逐元素)

import pandas as pd
# 创建一个Series
s = pd.Series([1, 2, 3, 4, 5])
# 定义函数:计算平方
def square(x):
    return x ** 2
# 使用apply
result = s.apply(square)
print(result)
# 输出:0 1 1 4 2 9 3 16 4 25

等同于map(),但apply()允许你传递额外参数(后文详述)。

2 对DataFrame应用函数(逐行或逐列)

关键参数是axis

  • axis=0(默认):函数应用到每一列(类似列遍历)
  • axis=1:函数应用到每一行(类似行遍历)
df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': [7, 8, 9]
})
# 按列计算总和(axis=0)
col_sum = df.apply(sum, axis=0)
print(col_sum)
# A 6 B 15 C 24
# 按行计算总和(axis=1)
row_sum = df.apply(sum, axis=1)
print(row_sum)
# 0 12 1 15 2 18

:axis=0和axis=1的方向怎么记忆?
:想象你的数据是一个Excel表格。axis=0是“从上往下压”,所以操作后得到的是每列的结果(列方向);axis=1是“从左往右压”,得到的是每行的结果(行方向)。


自定义函数与Lambda:让数据处理更灵活

1 使用lambda简化单行逻辑

对于简单操作,无需单独def,直接用lambda

# 将A列每个数加10
df['A'] = df['A'].apply(lambda x: x + 10)

2 自定义函数支持多参数与条件

假设你想根据性别和年龄计算“社保比例”:

def social_insurance(gender, age):
    if gender == '男' and age > 50:
        return 0.12
    elif gender == '女' and age > 45:
        return 0.10
    else:
        return 0.08
# 注意:apply只能传一个参数(行或列值),但可以通过lambda传递多列
df['社保比例'] = df.apply(lambda row: social_insurance(row['性别'], row['年龄']), axis=1)

3 传递额外参数:用argspartial

当函数需要固定参数时,使用args

def multiplier(x, factor):
    return x * factor
df['A'] = df['A'].apply(multiplier, args=(2,))  # 乘以2

实战案例:数据清洗、特征工程与条件计算

🔍 案例1:数据清洗——文本标准化

清洗一列“脏”名字,比如去除空格、统一大小写、替换特殊字符:

data = {'name': ['  alice ', 'BOB', 'charlie!', 'david_123']}
df = pd.DataFrame(data)
def clean_name(name):
    name = name.strip().lower()  # 去空格+小写
    name = ''.join(c for c in name if c.isalnum())  # 只保留字母数字
    return name.capitalize()  # 首字母大写
df['clean_name'] = df['name'].apply(clean_name)
print(df)

🔍 案例2:特征工程——基于多列生成评分

给电商订单分配“质量评分”:如果订单金额>100且退货率<0.05则评分高,否则中等或低:

def score_order(row):
    amount = row['amount']
    return_rate = row['return_rate']
    if amount > 200 and return_rate < 0.02:
        return '高'
    elif amount > 100 and return_rate < 0.05:
        return '中'
    else:
        return '低'
df['质量评分'] = df.apply(score_order, axis=1)

🔍 案例3:条件替换——复杂多规则映射

根据学生成绩反推等级(A/B/C/D),并且确保边界值处理:

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)

:什么时候用apply,什么时候用向量化操作?
:优先使用Pandas的向量化函数(如df['A'] + df['B']df['A'].str.replace()),因为速度最快,当你无法用纯向量化表达逻辑,如“根据多列条件做分支判断”,或者需要调用外部库(如字符串正则、数值积分)时,再选用apply()


性能对比:Apply vs 向量化 vs Iterrows vs Map

方法 典型速度举例(100万行) 适用场景
向量化操作 ~5-15ms 标准数学运算、字符串方法
apply() ~50-200ms 复杂逻辑、多列组合、外部函数
iterrows() ~3-10s 需要索引控制、调试(极慢,避免)
map() ~20-50ms 简单一列映射(比apply快一点)

追求速度时,优先向量化;无法向量化时,用apply();绝对避免iterrows()做大循环。


高级技巧:Axis参数、Args传递、避免陷阱

🛠 技巧1:result_type='expand'返回DataFrame

当你返回的是列表或多值,用result_type展开:

def split_name(name):
    first, last = name.split(' ', 1)
    return first, last
df[['first', 'last']] = df['full_name'].apply(split_name, result_type='expand')

🛠 技巧2:用apply创建多列新特征

同时计算两列结果:

def compute_features(row):
    return pd.Series([row['A'] + row['B'], row['A'] * row['B']], index=['sum', 'product'])
new_df = df.apply(compute_features, axis=1)

⚠️ 陷阱1:修改原DataFrame的副作用

apply中的函数不应该修改DataFrame本身,而是返回新值,否则可能引发不可预测的bug。

⚠️ 陷阱2:类型变化导致性能下降

apply返回的数据类型可能变为object,导致后续操作变慢,可以用.astype()强制转换。


常见问题Q&A:面试真题与避坑指南

❓ Q:apply能替代循环吗?为什么它比for快?

Aapply底层是C语言优化的循环,比纯Python的for快很多,但它不是向量化,当数据量极大(>100万行)时,尽量用numpy或Pandas的内置函数。

❓ Q:apply对DataFrame的axis=1和直接写for row in df.itertuples()哪个好?

Aitertuples()iterrows()快,但仍然比apply慢,推荐用apply,除非需要访问索引或修改原DataFrame。

❓ Q:如何在apply中使用多个参数?

A:使用lambda包裹,或者用args关键字传入固定参数。

❓ Q:apply返回Series还是DataFrame?

A:当函数返回标量时,返回Series;返回列表或Series时,可通过result_type控制输出为DataFrame。


什么时候该用Apply?

场景 推荐方法
单列简单数学运算(加、减、乘) 向量化
单列复杂条件判断(多分支if-else) apply + 函数
多列组合生成新特征(如总分、乘积) apply + axis=1
字符串替换、正则匹配 向量化 .str 方法
调用外部API或复杂计算库 apply
需要索引信息或逐行调试 itertuples (少用)

Pandas的apply()不是万能的,但没有apply()是万万不能的,它能让你用Python的原生逻辑处理几乎所有数据变形任务,是数据科学面试中最高频的考点之一。

打开你的Jupyter Notebook,用上面的案例练习一遍,你会发现数据处理从未如此顺手,如果你还有任何疑问,欢迎在评论区留言讨论!

抱歉,评论功能暂时关闭!