Pandas数据处理——map、apply、applymap的异同

在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和applymap可以解决绝大部分这样的数据处理需求。

import pandas as pd
import numpy as np

# 创建数据集
boolean = ['True','False']
gender = ['男','女']
color = ['white','black','green']
data = pd.DataFrame({
    'height':np.random.randint(150,190,100),
    'weight':np.random.randint(40,90,100),
    'smoker':[boolean[x] for x in np.random.randint(0,len(boolean),100)],
    'gender':[gender[x] for x in np.random.randint(0,len(gender),100)],
    'age':np.random.randint(15,90,100),
    'color':[color[x] for x in np.random.randint(0,len(color),100)]    
})
data.head()
heightweightsmokergenderagecolor
018970False72green
115342False49black
217851False50white
317047True85black
416351False89green

Series数据处理

1. map

如果需要把数据集中的gender列的男替换为1,女替换为0。应该怎么做呢?

# 使用字典映射
data['gender_x'] = data['gender'].map({'男':1,'女':0})
data.head()
heightweightsmokergenderagecolorgender_x
018970False72green0
115342False49black0
217851False50white0
317047True85black1
416351False89green1
# 使用函数
def gender_map(x):
    gender = 1 if x =='男' else 0
    return gender
# 传入的函数名,不带括号
data['gender_x'] = data['gender'].map(gender_map)
data.head()
heightweightsmokergenderagecolorgender_x
018970False72green0
115342False49black0
217851False50white0
317047True85black1
416351False89green1

不论是利用字典还是函数进行映射,map方法都是把对应的数据逐个当作参数传入到字典或函数中,得到映射后的值。

2. apply

同时Series对象还有apply方法,apply方法的作用原理和map方法类似,区别在于apply能够传入功能更为复杂的函数。怎么理解呢?一起看看下面的例子。

假设在数据统计的过程中,年龄age列有较大误差,需要对其进行调整(加上或减去一个值),由于这个加上或减去的值未知,故在定义函数时,需要加多一个参数bias,此时用map方法是操作不了的**(传入map的函数只能接收一个参数)**,apply方法则可以解决这个问题。

def age_apply(x,bias):
    return x+bias

# 额外的参数需要单独给到
data['age_x'] = data['age'].apply(age_apply,bias=-3)
data.head()
heightweightsmokergenderagecolorgender_xage_x
018970False72green069
115342False49black046
217851False50white047
317047True85black182
416351False89green186

对于Series而言,map可以解决绝大多数的数据处理需求,但如果需要使用较为复杂的函数,则需要用到apply方法。

DataFrame数据

1. apply

对DataFrame而言,apply是非常重要的数据处理方法,它可以接收各种各样的函数(Python内置的或自定义的),处理方式很灵活,下面通过几个例子来看看apply的具体使用及其原理。

在进行具体介绍之前,首先需要介绍一下DataFrame中axis的概念,在DataFrame对象的大多数方法中,都会有axis这个参数,它控制了你指定的操作是沿着0轴还是1轴进行。axis=0代表操作对列columns进行,axis=1代表操作对行row进行。

假设现在需要对data中的数值列分别进行取对数和求和的操作,这时可以用apply进行相应的操作,因为是对列进行操作,所以需要指定axis=0

# 沿着0轴求和
df1 = data[['height','weight','age']].apply(np.sum,axis=0)
df1
height    16964
weight     6268
age        4728
dtype: int64
df2 = data[['height','weight','age']].apply(np.log,axis=0)
df2
heightweightage
05.2417474.2484954.276666
15.0304383.7376703.891820
25.1817843.9318263.912023
35.1357983.8501484.442651
45.0937503.9318264.488636
............
955.0562464.0073334.430817
965.0689044.3438054.127134
975.1704844.4188414.356709
985.1984974.3040653.433987
995.2203564.4659083.178054

100 rows × 3 columns

当沿着轴0(axis=0)进行操作时,会将各列(columns)默认以Series的形式作为参数,传入到你指定的操作函数中,操作后合并并返回相应的结果。

在数据集中,有身高和体重的数据,所以根据这个,我们可以计算每个人的BMI指数(体检时常用的指标,衡量人体肥胖程度和是否健康的重要标准),计算公式是:体重指数BMI=体重/身高的平方(国际单位kg/㎡),因为需要对每个样本进行操作,这里使用axis=1的apply进行操作,代码如下:

def BMI(series):
    weight = series['weight']
    height = series['height']
    BMI = weight/height**2
    
    return BMI

data['BMI'] = data.apply(BMI,axis=1)
data.head()
heightweightsmokergenderagecolorgender_xage_xBMI
018970False72green0690.001960
115342False49black0460.001794
217851False50white0470.001610
317047True85black1820.001626
416351False89green1860.001920

总结一下对DataFrame的apply操作:

  1. 当axis=0时,对每列columns执行指定函数;当axis=1时,对每行row执行指定函数。
  2. 无论axis=0还是axis=1,其传入指定函数的默认形式均为Series,可以通过设置raw=True传入numpy数组。
  3. 对每个Series执行结果后,会将结果整合在一起返回(若想有返回值,定义函数时需要return相应的值)
  4. 当然,DataFrame的apply和Series的apply一样,也能接收更复杂的函数,如传入参数等,实现原理是一样的,具体用法详见官方文档。

2. applymap

applymap的用法比较简单,会对DataFrame中的每个单元格执行指定函数的操作。

# 构建一个新的数据集
data2 = pd.DataFrame({
    'A':np.random.randn(5),
    'B':np.random.randn(5),
    'C':np.random.randn(5),
    'D':np.random.randn(5)
})
data2
ABCD
00.3199730.398420-0.421453-1.324070
10.5074600.5297720.6503970.645287
20.659481-0.858528-1.4002941.834288
31.2652541.6855372.031475-2.136325
4-2.6169670.023655-0.080487-0.694068

现在想将DataFrame中所有的值保留两位小数显示,使用applymap即可。

data2.applymap(lambda x:"%.2f" % x)
ABCD
00.320.40-0.42-1.32
10.510.530.650.65
20.66-0.86-1.401.83
31.271.692.03-2.14
4-2.620.02-0.08-0.69
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值