如何在Pandas中使用Apply方法
apply()方法是数据预处理中最常用的方法之一。
它简化了对pandas系列中的每个元素和pandas DataFrame中的每一行或每一列的函数应用。在本教程中,我们将学习如何在pandas中使用apply()方法--你需要了解Python和lambda函数的基本原理。如果你不熟悉这些,或者需要提高你的Python技能,你可能想试试我们的免费Python基础课程。
让我们直接进入,在 Pandas 系列上应用一个函数
系列是潘达的基础。它们本质上是带有轴标签的一维数组,称为索引。
创建系列对象有不同的方法(例如,我们可以用列表或字典初始化系列)。让我们用两个列表定义一个系列对象,其中包含学生姓名作为索引,学生的身高(厘米)作为数据。
import pandas as pd
import numpy as np
from IPython.display import display
students = pd.Series(data=[180, 175, 168, 190],
index=['Vik', 'Mehdi', 'Bella', 'Chriss'])
display(students)
print(type(students))
Vik 180
Mehdi 175
Bella 168
Chriss 190
dtype: int64
上面的代码返回students对象的内容和它的数据类型。
students对象的数据类型是Series,所以我们可以使用apply()方法对其数据应用任何函数。让我们看看如何将学生的身高从厘米转换为英尺。
def cm_to_feet(h):
return np.round(h/30.48, 2)
print(students.apply(cm_to_feet))
Vik 5.91
Mehdi 5.74
Bella 5.51
Chriss 6.23
dtype: float64
学生的身高被转换为小数点后两位的英尺。为此,我们首先定义了一个进行转换的函数,然后将函数名称不带括号地传递给apply()方法。apply()方法接收系列中的每个元素,并对其应用cm_to_feet()函数。
Pandas DataFrame上应用一个函数
在本节中,我们将学习如何使用apply()方法来操作数据框架中的列和行。
首先,让我们用下面的代码创建一个假的DataFrame,包含一个公司员工的个人信息。
data = pd.DataFrame({'EmployeeName': ['Callen Dunkley', 'Sarah Rayner', 'Jeanette Sloan', 'Kaycee Acosta', 'Henri Conroy', 'Emma Peralta', 'Martin Butt', 'Alex Jensen', 'Kim Howarth', 'Jane Burnett'],
'Department': ['Accounting', 'Engineering', 'Engineering', 'HR', 'HR', 'HR', 'Data Science', 'Data Science', 'Accounting', 'Data Science'],
'HireDate': [2010, 2018, 2012, 2014, 2014, 2018, 2020, 2018, 2020, 2012],
'Sex': ['M', 'F', 'F', 'F', 'M', 'F', 'M', 'M', 'M', 'F'],
'Birthdate': ['04/09/1982', '14/04/1981', '06/05/1997', '08/01/1986', '10/10/1988', '12/11/1992', '10/04/1991', '16/07/1995', '08/10/1992', '11/10/1979'],
'Weight': [78, 80, 66, 67, 90, 57, 115, 87, 95, 57],
'Height': [176, 160, 169, 157, 185, 164, 195, 180, 174, 165],
'Kids': [2, 1, 0, 1, 1, 0, 2, 0, 3, 1]
})
display(data)
EmployeeName Department HireDate Sex Birthdate Weight Height Kids
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1
4 Henri Conroy HR 2014 M 10/10/1988 90 185 1
5 Emma Peralta HR 2018 F 12/11/1992 57 164 0
6 Martin Butt Data Science 2020 M 10/04/1991 115 195 2
7 Alex Jensen Data Science 2018 M 16/07/1995 87 180 0
8 Kim Howarth Accounting 2020 M 08/10/1992 95 174 3
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1
data = pd.DataFrame({'EmployeeName': ['Callen Dunkley', 'Sarah Rayner', ' Jeanette Sloan', 'Kaycee Acosta', 'Henri Conroy', ' Emma Peralta', 'Martin Butt', 'Alex Jensen', 'Kim Howarth', 'Jane Burnett'],
'部门'。['会计', '工程', '工程', '人力资源', '人力资源', '数据科学', '数据科学', '会计', '数据科学'] 。
'HireDate': [2010, 2018, 2012, 2014, 2014, 2018, 2020, 2018, 2020, 2012],
'性别': ['m', 'f', 'f', 'f', 'm', 'f', 'm', 'm', 'f'] 。
'出生日期': ['04/09/1982', '14/04/1981', '06/05/1997', '08/01/1986', '10/10/1988', '12/11/1992', '10/04/1991', '16/07/1995', '08/10/1992', '11/10/1979'] 。
'重量'。[78, 80, 66, 67, 90, 57, 115, 87, 95, 57],
'身高': [176, 160, 169, 157, 185, 164, 195, 180, 174, 165],
'孩子'。[2, 1, 0, 1, 1, 0, 2, 0, 3, 1]
})
display(data)
雇员姓名 部门 雇用日期 性别 出生日期 体重 身高 孩子
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0
3 Kaycee Acosta HR 2014 女 08/01/1986 67 157 1
4 Henri Conroy HR 2014 男 10/10/1988 90 185 1
5 Emma Peralta HR 2018 女 12/11/1992 57 164 0
6 Martin Butt 数据科学 2020 男 10/04/1991 115 195 2
7 Alex Jensen 数据科学 2018 男 16/07/1995 87 180 0
8 Kim Howarth 会计 2020 男 08/10/1992 95 174 3
9 Jane Burnett 数据科学 2012 女 11/10/1979 57 165 1
注意
在本节中,我们将研究由公司人力资源部门发起的假请求。我们将通过不同的场景来学习如何使用apply()方法。我们将在每个场景中探索一个新的用例,并使用apply()方法解决它。
场景1
我们假设人力资源部门想发送一封邀请邮件,邮件的开头是对所有员工的友好问候(例如,嘿,Sarah!)
他们要求你创建两列,分别存储员工的名和姓,这样就可以很容易地提到员工的名字。要做到这一点,我们可以使用一个lambda函数,在通过指定的分隔符将字符串分割成一个列表;split()方法的默认分隔符是任何白色空间。让我们看一下代码。
data['FirstName'] = data['EmployeeName'].apply(lambda x : x.split()[0])
data['LastName'] = data['EmployeeName'].apply(lambda x : x.split()[1])
display(data)
EmployeeName Department HireDate Sex Birthdate Weight Height Kids FirstName LastName
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2 Callen Dunkley
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1 Sarah Rayner
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0 Jeanette Sloan
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1 Kaycee Acosta
4 Henri Conroy HR 2014 M 10/10/1988 90 185 1 Henri Conroy
5 Emma Peralta HR 2018 F 12/11/1992 57 164 0 Emma Peralta
6 Martin Butt Data Science 2020 M 10/04/1991 115 195 2 Martin Butt
7 Alex Jensen Data Science 2018 M 16/07/1995 87 180 0 Alex Jensen
8 Kim Howarth Accounting 2020 M 08/10/1992 95 174 3 Kim Howarth
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett
在上面的代码中,我们在EmployeeName列上应用了lambda函数,从技术上讲,它是一个Series对象。lambda函数将雇员的全名拆分为名和姓。因此,代码又创建了两列,包含了雇员的名和姓。
情景二
现在,我们假设人力资源部门想知道每个员工的年龄和员工的平均年龄,因为他们想确定员工的年龄是否会影响工作满意度和工作投入。
为了完成这项工作,第一步是定义一个函数,获取员工的出生日期并返回其年龄。
def calculate_age(birthdate):
birthdate = datetime.strptime(birthdate, '%d/%m/%Y').date()
today = date.today()
return today.year - birthdate.year - (today.month < birthdate.month)
函数calculate_age()以适当的格式获得一个人的出生日期,在对其进行简单计算后,返回他们的年龄。
下一步是使用apply()方法在DataFrame的Birthdate列上应用该函数,如下所示。
data['Age'] = data['Birthdate'].apply(calculate_age)
display(data)
EmployeeName Department HireDate Sex Birthdate Weight Height Kids FirstName LastName Age
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2 Callen Dunkley 39
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1 Sarah Rayner 40
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0 Jeanette Sloan 24
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1 Kaycee Acosta 36
4 Henri Conroy HR 2014 M 10/10/1988 90 185 1 Henri Conroy 33
5 Emma Peralta HR 2018 F 12/11/1992 57 164 0 Emma Peralta 29
6 Martin Butt Data Science 2020 M 10/04/1991 115 195 2 Martin Butt 30
7 Alex Jensen Data Science 2018 M 16/07/1995 87 180 0 Alex Jensen 26
8 Kim Howarth Accounting 2020 M 08/10/1992 95 174 3 Kim Howarth 29
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett 42
雇员姓名 部门 雇用日期 性别 出生日期 体重 身高 孩子 名字 姓氏 年龄
上面的单行语句在Birthdate列的每个元素上应用calculate_age()函数,并将返回的值存储在Age列。
最后一步是计算雇员的平均年龄,如下所示。
print(data['Age'].mean())
32.8
情景3
公司的人力资源经理正在探索为所有员工提供医疗保障的方案。潜在的供应商需要有关雇员的信息。由于DataFrame包含每个员工的体重和身高,让我们假设人力资源经理要求你提供每个员工的身体质量指数(BMI),这样她就可以从潜在的医疗保健供应商那里获得报价。
要完成这个任务,首先,我们需要定义一个计算身体质量指数(BMI)的函数。BMI的公式是体重(公斤)除以身高(米)的平方。因为员工的身高是以厘米为单位的,所以我们需要用身高除以100来得到米的身高。让我们来实现这个函数。
def calc_bmi(weight, height):
return np.round(weight/(height/100)**2, 2)
下一步是在DataFrame上应用该函数。
data['BMI'] = data.apply(lambda x: calc_bmi(x['Weight'], x['Height']) , axis=1)
这个lambda函数接收每一行的体重和身高值,然后对它们应用calc_bmi()函数来计算其BMI。axis=1参数意味着在DataFrame中迭代行数。
display(data)
EmployeeName Department HireDate Sex Birthdate Weight Height Kids FirstName LastName Age BMI
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2 Callen Dunkley 39 25.18
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1 Sarah Rayner 40 31.25
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0 Jeanette Sloan 24 23.11
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1 Kaycee Acosta 36 27.18
4 Henri Conroy HR 2014 M 10/10/1988 90 185 1 Henri Conroy 33 26.30
5 Emma Peralta HR 2018 F 12/11/1992 57 164 0 Emma Peralta 29 21.19
6 Martin Butt Data Science 2020 M 10/04/1991 115 195 2 Martin Butt 30 30.24
7 Alex Jensen Data Science 2018 M 16/07/1995 87 180 0 Alex Jensen 26 26.85
8 Kim Howarth Accounting 2020 M 08/10/1992 95 174 3 Kim Howarth 29 31.38
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett 42 20.94
最后一步是根据BMI的测量结果对员工进行分类。BMI小于18.5为第一组,18.5到24.9之间为第二组,25到29.9之间为第三组,30以上为第四组。为了实现这个解决方案,我们将定义一个函数来返回各种BMI指标,然后在DataFrame的BMI列上应用这个函数来查看每个员工属于哪一类。
def indicator(bmi):
if (bmi < 18.5):
return 'Group One'
elif (18.5 <= bmi < 25):
return 'Group Two'
elif (25 <= bmi < 30):
return 'Group Three'
else:
return 'Group Four'
data['BMI_Indicator'] = data['BMI'].apply(indicator)
display(data)
EmployeeName Department HireDate Sex DoB Weight Height Kids FirstName LastName Age BMI BMI_Indicator
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2 Callen Dunkley 39 25.18 Group Three
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1 Sarah Rayner 40 31.25 Group Four
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0 Jeanette Sloan 24 23.11 Group Two
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1 Kaycee Acosta 36 27.18 Group Three
4 Henri Conroy HR 2014 M 10/10/1988 90 185 1 Henri Conroy 33 26.30 Group Three
5 Emma Peralta HR 2018 F 12/11/1992 57 164 0 Emma Peralta 29 21.19 Group Two
6 Martin Butt Data Science 2020 M 10/04/1991 115 195 2 Martin Butt 30 30.24 Group Four
7 Alex Jensen Data Science 2018 M 16/07/1995 87 180 0 Alex Jensen 26 26.85 Group Three
8 Kim Howarth Accounting 2020 M 08/10/1992 95 174 3 Kim Howarth 29 31.38 Group Four
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett 42 20.94 Group Two
场景4
让我们假设新年即将来临,公司管理层宣布那些有10年以上工作经验的员工将获得额外的奖金。人力资源经理想知道谁有资格获得奖金。
要准备请求的信息,需要在HireDate列上应用下面的lambda函数,如果当前年份和雇佣年份之间的差值大于或等于十年,则返回True,否则返回False。
mask = data['HireDate'].apply(lambda x: date.today().year - x >= 10)
print(mask)
0 True
1 False
2 True
3 False
4 False
5 False
6 False
7 False
8 False
9 True
Name: HireDate, dtype: bool
为了显示合格的员工,我们使用布尔掩码过滤DataFrame行。让我们运行下面的语句并查看结果:
显示(数据(员工画像))
雇员名部门雇佣日期性别年龄体重身高孩子名字姓年龄bmi
EmployeeName Department HireDate Sex DoB Weight Height Kids FirstName LastName Age BMI
0 Callen Dunkley Accounting 2010 M 04/09/1982 78 176 2 Callen Dunkley 39 25.18
2 Jeanette Sloan Engineering 2012 F 06/05/1997 66 169 0 Jeanette Sloan 24 23.11
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett 42 20.94
0 callen dunkley会计2010 m 04/09/1982 78 176 2 callen dunkley 39 25.18
2珍妮特斯隆工程2012 f 06/05/1997 66 169 0珍妮特斯隆24 23.11
9简·伯内特数据科学2012 f 11/10/1979 57 165 1简·伯内特42 20.94
场景5
假设明天是母亲节,公司为所有有孩子的女性员工准备了一份母亲节礼物。人力资源团队让你准备一份有资格获得这份礼物的员工名单。要完成这项任务,我们需要编写一个简单的lambda函数,该函数考虑Sex和Kids列以提供所需的结果,如下所示:
data[data.apply(lambda x: True if x ['Gender'] == 'F' and x['Kids'] > 0 else False, axis=1)]
EmployeeName Department HireDate Sex Birthdate Weight Height Kids FirstName LastName Age BMI
1 Sarah Rayner Engineering 2018 F 14/04/1981 80 160 1 Sarah Rayner 40 31.25
3 Kaycee Acosta HR 2014 F 08/01/1986 67 157 1 Kaycee Acosta 36 27.18
9 Jane Burnett Data Science 2012 F 11/10/1979 57 165 1 Jane Burnett 42 20.94
运行上面的代码将返回将收到礼物的员工列表。
如果女性员工至少有一个孩子,lambda函数返回True;否则,返回False。在DataFrame上应用lambda函数的结果是一个布尔掩码,我们直接使用它来过滤DataFrame的行。
结论
在本教程中,我们通过不同的示例了解了apply()方法的作用以及如何使用它。apply()方法是对pandas中的Series或DataFrame的每个值应用函数的一种强大而有效的方法。由于apply()方法使用了Python的C扩展,所以当遍历pandas DataFrame的所有行时,它执行得更快。但是,这不是一般的规则,因为通过列执行相同的操作会比较慢。
网友评论