学习Pandas的apply()函数

203 阅读7分钟

在本教程中,我们将学习如何使用apply() 函数将一个函数应用于Pandas数据框或序列。使用这个工具,我们可以应用任何种类的函数来隔离我们的数据,并通过非常有限的代码来改变它。

语法

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

func:函数

要应用于每一列或每一行的函数。

轴。{0或 "索引",1或 "列"},默认为0

应用该函数的轴。

  • 0 或'index': 对每一列应用函数。
  • 1或'columns' :将函数应用于每一行。

raw:bool, default False

决定行或列是否以系列 或ndarray对象形式传递。

  • False: 将每一行或每一列作为一个系列传给函数。
  • True: 传递的函数将接收ndarray对象,而不是。如果你只是应用一个NumPy 还原函数,这将获得更好的性能。

result_type:{'expand', 'reduce', 'broadcast', None}, 默认 None

这些只在axis=1 (列)时作用。

  • 'expand':列表式的结果将被转化为列。
  • 'reduce': 如果可能的话,返回一个系列,而不是扩展列表状的结果。这与'expand' 相反。
  • 'broadcast':结果将被广播成原始形状的DataFrame ,原始索引和列将被保留。

默认行为(None)取决于应用函数的返回值:列表状的结果将作为一个系列返回。然而,如果应用函数返回一个系列,这些将被扩展为列。

args:元组

除了数组/系列之外,要传递给func的位置参数。

**额外的关键字参数

额外的关键字参数,作为关键字参数传递给func

返回:系列或数据框架

沿着DataFrame的给定轴线应用func 的结果。

一个介绍性的例子

为了开始,让我们看一下一个介绍性的例子。

import pandas as pd

df = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]], 
    columns=["Col 1", "Col 2", "Col 3"], 
    index=["Row 1", "Row 2", "Row 3"])

这是产生的DataFrame。

第1栏第2列第3列
第1行123
第2行456
第3行789

在第一步,我们导入Pandas。然后,我们创建一个潘达斯数据框 ,里面充满了从1到9的数值。输出显示了一个典型的Pandas数据框。

现在,我们使用apply() 函数。

df.apply(sum)

输出:

Col 1    12
Col 2    15
Col 3    18
dtype: int64

apply() 函数期望在我们的数据集上执行一个函数。通过输入关键词"sum",我们说明我们想使用内置的Python函数"[sum()](https://blog.finxter.com/python-sum/ "Python sum() – A Simple Illustrated Guide")"来应用于我们的数据集。输出显示了每一列的总和以及输出值的数据类型。我们可以看到,数据类型是 "int64",因为总和是整数值。

定义应用函数的坐标轴

在上面的例子中,我们没有说明沿着哪个轴来应用函数,输出计算了每一列的总和。这是因为可选的 "axis" 参数默认设置为 "0",对每一列应用函数。

不过,也可以把这个参数改为 "1"。

df.apply(sum, axis=1)

输出:

Row 1     6
Row 2    15
Row 3    24
dtype: int64

在这里,我们的做法与之前一样,但这一次,我们使用 "axis" 参数并将其指定为 "1"。这样,我们将sum() 函数应用于每一行而不是每一列。

如果你不喜欢使用 "1 "和 "0",你可以应用字符串"columns" 来代替 "1",应用字符串"index" 来代替 "0"。

df.apply(sum, axis="columns")

输出:

Row 1     6
Row 2    15
Row 3    24
dtype: int64

输出结果与之前一样,我们将 "axis" 参数分配为 "1"。axis" 参数"columns" 输出的是每一行的值,而不是每一列的值,这可能有点令人困惑。这是因为我们想在这里按列计算总和。例如,"第1行 "的结果是 "6"。而这是通过对第1行的第1、2、3列的值进行加总计算出来的。

应用一个内置的函数

如前所述,我们在上面的例子中用来应用于我们的数据集的sum()函数是一个内置的Python函数。在 Pandas 中,有几十个其他的 Python 内置函数,我们可以与 apply() 函数结合使用。例如,max()和min()函数。

df.apply(max)

输出:

Col 1    7
Col 2    8
Col 3    9

df.apply(min)

结果:

Col 1    1
Col 2    2
Col 3    3
dtype: int64

正如名字所示,这些函数分别计算最大值最小值

除此之外,我们还可以使用潘达斯的内置函数。

df.apply(pd.notnull)

结果:

第1栏第2列第3列
第1行
第2行真实
第3行真实

在这里,我们在apply() 方法中使用notnull() 函数。这个函数可以检测一个值是否存在。换句话说,它检查一个值是否是 "null "或 "NA "值。如果该值存在,它将打印 出"True"。由于我们的数据集只包含整数值,所以输出的数据框中充满了 "True"值。

我们通过在函数前添加 "pd 。"来说明我们使用了一个内置的Pandas函数。

与此类似,我们也能够使用其他库的函数,例如Numpy库。

import numpy as np

df.apply(np.sqrt)

下面是生成的DataFrame。

第1栏第2栏第3列
第1行1.000.0001.414.2141.732.051
第2行2.000.0002.236.0682.449.490
第3行2.645.7512.828.4273.000.000

首先,我们必须导入Numpy库以便能够使用Numpy函数。在这种情况下,我们将apply() ,Numpy函数sqrt() ,计算数据框中每个值的平方根。

应用自定义函数

内置函数很适合应用于我们的数据集,因为它们很容易使用,对于很多用例来说,有一个内置函数可以完美地解决我们的问题。然而,有时我们想做一些非常具体的计算,但却没有内置函数可以使用。对于这些情况,我们定义我们自己的函数,apply

比方说,我们想对我们的数据集进行分类。如果一个值在1到3之间,它就是小的,如果一个值在4到6之间,这个值就是正常的,如果一个值大于6,它就是大的。

没有内置的函数来实现这一点,所以我们设置了我们自己的函数。

def categorize(x):
    if x <= 3:
        return "small"
    elif x > 3 and x <= 6:
        return "normal"
    else:
        return "big"

这个函数所做的正是我们刚才描述的。现在,我们把这个函数附加到apply() 方法中。假设我们要对第1列进行分类。

df["Col 1"].apply(categorize)

结果:

Row 1     small
Row 2    normal
Row 3       big
Name: Col 1, dtype: object

我们把categorize() 函数放在apply() 方法里面。输出显示了第1列中每个值的类别。如果我们将其与初始数据框进行比较,我们可以看到分类工作已经成功进行。

使用Lambda函数

有时,自定义函数非常短,只有一个表达式。在这种情况下,有一种更有效、更方便的方式将函数应用到我们的数据框中,它被称为Lambda函数。lambda函数是一个适合于一行的小函数,没有函数名。

比方说,我们想把 "2 "加到我们数据框中的每个值上。我们可以应用一个像这样的常规Python函数。

def plus2(x):
    return x + 2

然后,把这个函数追加到我们的apply() 函数中。

df.apply(plus2)

结果:

第1栏第2栏第3列
第1行345
第2行678
第三行91011

这种方法是有效的,但它是不必要的冗长。我们使用lambda函数只用一行就能达到同样的效果。

df.apply(lambda x: x+2)

结果:

第1栏第2栏第3列
第1行345
第2行678
第三行91011

一个lambda函数的结构是这样的。

lambda arguments: expression

它以关键字 "lambda"开始,后面是参数,然后是表达式。注意,我们这里只有一个表达式。这就是为什么lambda函数对多个表达式不起作用。我们之前创建的categorize() 函数就不可能用 lambda 函数来创建,因为有多个表达式。

然而,在这个用例中,我们只在每个值上添加 "2",lambda函数为我们提供了足够的机会,在这里使用更优雅。

总结

总而言之,在使用Pandas时,apply() 函数是一个非常重要的工具。它允许我们在数据帧上执行任何类型的函数,无论是Python、Pandas、Numpy或任何其他Python库的内置函数,还是自定义函数。此外,我们可以在每个轴上操作这些函数,这给了我们更多的机会来进行计算和分析我们的数据。