在本教程中,我们将学习如何使用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行 | 1 | 2 | 3 |
| 第2行 | 4 | 5 | 6 |
| 第3行 | 7 | 8 | 9 |
在第一步,我们导入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.000 | 1.414.214 | 1.732.051 |
| 第2行 | 2.000.000 | 2.236.068 | 2.449.490 |
| 第3行 | 2.645.751 | 2.828.427 | 3.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行 | 3 | 4 | 5 |
| 第2行 | 6 | 7 | 8 |
| 第三行 | 9 | 10 | 11 |
这种方法是有效的,但它是不必要的冗长。我们使用lambda函数只用一行就能达到同样的效果。
df.apply(lambda x: x+2)
结果:
| 第1栏 | 第2栏 | 第3列 | |
| 第1行 | 3 | 4 | 5 |
| 第2行 | 6 | 7 | 8 |
| 第三行 | 9 | 10 | 11 |
一个lambda函数的结构是这样的。
lambda arguments: expression
它以关键字 "lambda"开始,后面是参数,然后是表达式。注意,我们这里只有一个表达式。这就是为什么lambda函数对多个表达式不起作用。我们之前创建的categorize() 函数就不可能用 lambda 函数来创建,因为有多个表达式。
然而,在这个用例中,我们只在每个值上添加 "2",lambda函数为我们提供了足够的机会,在这里使用更优雅。
总结
总而言之,在使用Pandas时,apply() 函数是一个非常重要的工具。它允许我们在数据帧上执行任何类型的函数,无论是Python、Pandas、Numpy或任何其他Python库的内置函数,还是自定义函数。此外,我们可以在每个轴上操作这些函数,这给了我们更多的机会来进行计算和分析我们的数据。