Pandas 实战指南:如何高效地将函数应用到单列或多列

在日常的数据处理工作中,我们经常需要对 DataFrame 中的特定列进行批量操作。无论是数据清洗、格式转换,还是基于业务逻辑的复杂计算,掌握如何灵活地应用函数都是一项核心技能。今天,我们将深入探讨 Pandas 中的 apply 方法,学习如何将自定义函数、Lambda 表达式甚至是 NumPy 函数高效地应用到数据集的某一列、多列乃至整个 DataFrame 中。通过这篇文章,你将掌握处理复杂数据转换的实用技巧,并学会如何优化代码的可读性与性能。

理解 apply 方法的基础

在我们开始编写代码之前,先来快速回顾一下 INLINECODEef53afe7 方法的基本机制。简单来说,INLINECODE8e9d4976 允许我们将一个函数(无论是内置的、自定义的还是匿名函数)沿着 DataFrame 的轴(行或列)进行广播。

#### 核心语法与参数

DataFrame.apply 的用法非常灵活,其基本语法如下:

> 语法: DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwds)

为了更有效地使用它,我们需要了解几个关键参数的作用:

  • INLINECODEc83fac94: 这是我们想要应用的核心函数。它可以是一个 Python 内置函数(如 INLINECODEf16fc9df),一个自定义函数,或者是一个 Lambda 表达式。
  • INLINECODEd6868685: 这个参数决定了函数应用的方向。INLINECODE12015176(默认)表示将函数应用到每一列(垂直方向),而 axis=1 表示应用到每一行(水平方向)。在我们的多列应用场景中,理解这个参数至关重要。
  • INLINECODE272f2a57: 这是一个布尔值。默认为 INLINECODE3ab567d0,意味着行或列将作为 Series 对象传递给函数。如果设置为 True,则传递原始的 ndarray 对象,这在某些需要极高性能的场景下会更有用。
  • INLINECODEb3266062: 这个参数仅在 INLINECODE442d4325(列方向)时生效。它控制返回结果的类型。可选值包括 INLINECODEbe760f17(返回列表式的 DataFrame),INLINECODEa0ade9b3(返回 Series),或 ‘broadcast‘(结果广播到原始数据的形状)。
  • args: 这是一个元组,用于向函数传递额外的位置参数。
  • **kwds: 用于向函数传递额外的关键字参数。

场景一:单列数据的精准处理

让我们从最基础但也最常见的场景开始:将函数应用到单个列。假设我们有一个包含用户信息的 DataFrame,我们需要对用户的年龄进行调整。

#### 示例 1:使用自定义函数处理单列

在这个例子中,我们定义了一个简单的函数 add_two,旨在将所有人的年龄增加 2 岁。这种方法非常适合逻辑稍微复杂一些、不适合用一行 Lambda 表达式表达的情况。

# 导入 Pandas 模块
import pandas as pd
import numpy as np

# 构建示例 DataFrame
data = {
    ‘Name‘: [‘Tom‘, ‘Nick‘, ‘Krish‘, ‘Jack‘],
    ‘Age‘: [32, 24, 33, 21]
}
df = pd.DataFrame(data)

# 定义一个用于增加年龄的函数
def add_two(age):
    """将输入的年龄加 2"""
    return age + 2

# 将函数应用到 ‘Age‘ 列
# 注意:这里我们使用 df[‘Age‘] 选中单列,返回的是 Series
# apply 会遍历 Series 中的每一个元素
 df[‘Age‘] = df[‘Age‘].apply(add_two)

# 展示处理后的 DataFrame
print("增加 2 岁后的结果:")
print(df)

输出结果:

    Name  Age
0    Tom   34
1   Nick   26
2  Krish   35
3   Jack   23

场景二:跨列操作与多列处理

当你需要同时处理多列数据时,apply 的强大之处就体现出来了。我们可以一次性选中多个列,并对其进行统一处理。这在数据清洗阶段(例如统一给字符串添加前缀或后缀)非常有用。

#### 示例 2:将函数应用到多列

假设我们有一个包含两列字符串的数据集,现在的任务是给所有名字加上 INLINECODE2c56d038 的前缀。我们可以通过 INLINECODE105bf999 的切片语法选中多列,然后调用 apply

# 创建包含两列字符串的 DataFrame
df_str = pd.DataFrame({
    ‘First_Name‘: [‘Tom‘, ‘Nick‘, ‘Krish‘, ‘Jack‘], 
    ‘Last_Name‘: [‘Hardy‘, ‘Jonas‘, ‘Adams‘, ‘Ma‘]
})

# 定义一个用于添加前缀的函数
def add_prefix(name):
    """在名字前添加 ‘Geek_‘"""
    return ‘Geek_‘ + name

# 选择多列并应用函数
# 注意:这里是对选中的 DataFrame 的每一列调用 apply
# 默认 axis=0,即按列向下传递
df_str[[‘First_Name‘, ‘Last_Name‘]] = df_str[[‘First_Name‘, ‘Last_Name‘]].apply(add_prefix)

print("添加前缀后的结果:")
print(df_str)

输出结果:

  First_Name Last_Name
0    Geek_Tom  Geek_Hardy
1   Geek_Nick  Geek_Jonas
2  Geek_Krish  Geek_Adams
3   Geek_Jack    Geek_Ma

场景三:全量数据的数值变换

有时候,我们需要对 DataFrame 中的所有数值型列执行相同的数学运算。此时,直接对整个 DataFrame 调用 apply 是最高效的方式。

#### 示例 3:对所有列进行数学运算

在这个案例中,我们有一个包含整数、浮点数和偶数的表格,我们将把所有列的数值都乘以 2。这是一个典型的数据预处理场景,常用于特征缩放或单位转换。

# 创建数值型 DataFrame
df_num = pd.DataFrame({
    ‘Integers‘: [1, 2, 3, 4, 5], 
    ‘Float‘: [1.1, 2.2, 3.3, 4.4, 5.5],
    ‘Even_no‘: [2, 4, 6, 8, 10]
})

# 定义乘法函数
def multiply_by_2(x):
    return x * 2

# 对整个 DataFrame 应用函数
# Pandas 会智能地将函数应用到每一列
 df_num = df_num.apply(multiply_by_2)

print("所有数值乘以 2 后的结果:")
print(df_num)

输出结果:

   Integers  Float  Even_no
0         2    2.2        4
1         4    4.4        8
2         6    6.6       12
3         8    8.8       16
4        10   11.0       20

场景四:结合 NumPy 进行高性能计算

Pandas 与 NumPy 是天生的搭档。对于标准的数学运算(如平方、开方、对数等),直接使用 NumPy 的通用函数通常比手写 Python 循环或普通 Python 函数要快得多。

#### 示例 4:利用 NumPy 函数处理单列

让我们来看一个实际的例子,我们需要对 INLINECODEfaa61a2c 列中的每一个数值求平方。我们可以直接传入 INLINECODE9416e375。

# 重新定义数据以供演示
df_math = pd.DataFrame({
    ‘Integers‘: [1, 2, 3, 4, 5], 
    ‘Float‘: [1.1, 2.2, 3.3, 4.4, 5.5],
    ‘Even_no‘: [2, 4, 6, 8, 10]
})

# 直接应用 numpy.square 函数到指定列
# 这种方式利用了向量化操作,效率极高
df_math[‘Integers‘] = df_math[‘Integers‘].apply(np.square)

print("Integers 列求平方后的结果:")
print(df_math)

输出结果:

   Integers  Float  Even_no
0         1    1.1        2
1         4    2.2        4
2         9    3.3        6
3        16    4.4        8
4        25    5.5       10

场景五:Lambda 表达式的灵活应用

对于简单的逻辑,定义一个具名函数可能会显得有些繁琐。此时,Python 的 Lambda(匿名)函数结合 apply 可以让代码更加简洁优雅。

#### 示例 5:使用 Lambda 对所有列进行操作

假设我们需要将 DataFrame 中的所有数值都加上 5。使用 Lambda,我们可以在一行代码内完成定义和应用。

df_lambda = pd.DataFrame({
    ‘Integers‘: [1, 2, 3, 4, 5], 
    ‘Float‘: [1.1, 2.2, 3.3, 4.4, 5.5],
    ‘Even_no‘: [2, 4, 6, 8, 10]
})

# 使用 Lambda 表达式对全表进行操作
# x 代表每一列(Series)
df_lambda = df_lambda.apply(lambda x: x + 5)

print("使用 Lambda 加 5 后的结果:")
print(df_lambda)

输出结果:

   Integers  Float  Even_no
0       6.0    6.1        7
1       7.0    7.2        9
2       8.0    8.3       11
3       9.0    9.4       13
4      10.0   10.5       15

进阶实战:多列协同处理与最佳实践

除了上述的基础用法,我们在实际开发中还会遇到更复杂的情况,比如需要同时引用多列的值来计算结果,并生成一列新数据。这是 apply 最强大的用法之一,但也是初学者容易踩坑的地方。

#### 示例 6:按行处理多列数据(Axis=1)

假设我们有一个包含“单价”和“数量”的销售数据表,现在需要计算“总价”。这涉及到每一行的两列数据。此时,我们需要设置 axis=1

df_sales = pd.DataFrame({
    ‘Product‘: [‘Apple‘, ‘Banana‘, ‘Cherry‘],
    ‘Price‘: [10, 5, 20],
    ‘Quantity‘: [3, 10, 2]
})

# 定义计算总价的函数
def calculate_total(row):
    # 当 axis=1 时,传入的 row 是一个 Series 对象,包含了该行所有列的数据
    return row[‘Price‘] * row[‘Quantity‘]

# 使用 apply,并指定 axis=1
df_sales[‘Total_Price‘] = df_sales.apply(calculate_total, axis=1)

print("销售数据计算结果:")
print(df_sales)

输出结果:

   Product  Price  Quantity  Total_Price
0    Apple     10         3           30
1   Banana      5        10           50
2   Cherry     20         2           40

性能优化与常见陷阱

在使用 apply 时,为了保证代码的高效和稳定,我们需要注意以下几点:

  • 优先使用向量化操作:虽然 INLINECODE7aa945df 很灵活,但它本质上是在 Python 层面进行循环。如果可能,尽量使用 Pandas 或 NumPy 内置的向量化运算符(如 INLINECODEe772ab0c),这比 apply 快得多。
  • 避免在 INLINECODEf3303d51 中修改 DataFrame:永远不要在 INLINECODEf27aa3ac 的函数体内去修改原始的 DataFrame(例如 INLINECODE3b5a59e4),这会导致不可预知的错误或性能问题。INLINECODEb8597f05 应该只返回新的值。
  • 注意数据类型:在处理多列时,确保所选列的数据类型是兼容的。如果你试图对包含字符串和数字的列同时应用数学函数,Pandas 会抛出错误。

总结

在这篇文章中,我们全面探索了 Pandas 中 INLINECODE8e87a919 函数的各种用法。从最基础的单列数据处理,到涉及多列协同的复杂计算,INLINECODE17457fbb 提供了一套极其强大的工具集来应对各种数据变换需求。

通过掌握这些技巧,你将能够编写出更简洁、更“Pandas 风格”的代码,告别繁琐的 INLINECODEd80a5db8 循环。下次当你面对需要进行批量处理的数据表时,不妨停下来思考一下:“我可以用 INLINECODE73880201 更优雅地解决这个问题吗?” 相信我,你的数据科学工作流将会因此变得更加高效。

现在,打开你的 Python 编辑器,尝试将这些方法应用到你的实际项目中去吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/21172.html
点赞
0.00 平均评分 (0% 分数) - 0