pandas中 map,apply,applymap的用法和进度条设置

在pandas中一般有两种数据结构对象Series、DataFrame。想要批量精心化操作Series、DataFrame就需要使用配套方法:map、apply和applymap

一、在Series中使用map、apply方法

构造实验数据集

import pandas as pd
import numpy as np
boolean=[True,False]
gender=["男","女"]
color=["white","black","yellow"]
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,2,100)],
    "gender":[gender[x] for x in np.random.randint(0,2,100)],
    "age":np.random.randint(15,90,100),
    "color":[color[x] for x in np.random.randint(0,len(color),100) ]
})

在这里插入图片描述

1、Series.map(arg, na_action=None)

参数:
arg : function, dict, or Series
na_action : 取值为 {None, ‘ignore’}, 默认为 None
返回值:
Pandas Series with same as index as caller
1、把数据集中gender列的男替换为1,女替换为0,怎么做呢?

①使用字典进行映射

data["gender"] = data["gender"].map({"男":1, "女":0})

结果:
在这里插入图片描述
②使用函数

def gender_map(x):
    gender = 1 if x == "男" else 0
    return gender
# 注意这里传入的是函数名,不带括号
data["gender"] = data["gender"].map(gender_map)
# 或者
data["gender"] = data["gender"].map(lambda x:1 if x=='男' else 0)

在这里插入图片描述
在这里插入图片描述
即按元素执行字典匹配或者传入并执行函数

2、Series.apply()

Series对象还有apply方法,apply方法的作用原理和map方法类似,区别在于apply能够传入功能更为复杂的函数。即apply函数可以传入多个参数值而map只能传入一个参数值
如:
1、将数据集中的年龄列中的年龄都加5

def apply_age(x,bias):
    return x+bias
#以元组的方式传入额外的参数
data["age"] = data["age"].apply(apply_age,args=(5,))

结果:
在这里插入图片描述

二、在 DataFrame中使用apply和applymap方法

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

参 数:
1、func : function 应用到每行或每列的函数。

2、axis :{0 or ‘index’, 1 or ‘columns’}, default 0 函数应用所沿着的轴。

0 or index : 在每一列上应用函数。
1 or columns : 在每一行上应用函数。
在这里插入图片描述

3、raw : bool, default False 确定行或列以Series还是ndarray对象传递。

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

4、result_type : {‘expand’, ‘reduce’, ‘broadcast’, None}, default None 只有在axis=1列时才会发挥作用。

expand : 列表式的结果将被转化为列。
reduce : 如果可能的话,返回一个Series,而不是展开类似列表的结果。这与expand 相反。
broadcast : 结果将被广播到 DataFrame 的原始形状,原始索引和列将被保留。
默认行为(None)取决于应用函数的返回值:类似列表的结果将作为这些结果的 Series 返回。但是,如果应用函数返回一个 Series
,这些结果将被扩展为列。

5、args : tuple 除了数组/序列之外,要传递给函数的位置参数。

6、**kwds: 作为关键字参数传递给函数的附加关键字参数。

1、对data中的数值列分别进行取对数和求和的操作
因为是对列进行操作,所以需要指定axis=0

# 沿着0轴求和
data[["height","weight","age"]].apply(np.sum, axis=0)# 沿着0轴取对数
data[["height","weight","age"]].apply(np.log, axis=0)

结果分别为:
在这里插入图片描述
在这里插入图片描述
执行过程(数据不一样但是不妨碍我们理解):
在这里插入图片描述
在这里插入图片描述
即axis=0时 apply传入数的数据是dadaframe的每一列数据,函数操作的是每一列数据(series)。操作后合并并返回相应的结果。
2、计算每个人的BMI指数(体检时常用的指标,衡量人体肥胖程度和是否健康的重要标准),计算公式是:体重指数BMI=体重/身高的平方(国际单位kg/㎡)

def BMI(series):
    weight = series["weight"]
    height = series["height"]/100
    BMI = weight/height**2
    return BMI
data["BMI"] = data.apply(BMI,axis=1)

结果:
在这里插入图片描述
执行过程:
在这里插入图片描述
即axis=1时 apply传入数的数据是dadaframe的每一行数据,函数操作的是每一行数据(series)。操作后合并并返回相应的结果。

2、 applymap()

applymap的用法比较简单,会对DataFrame中的每个单元格执行指定函数的操作,虽然用途不如apply广泛,但在某些场合下还是比较有用的,如下面这个例子。

df = pd.DataFrame(
    {
        "A":np.random.randn(5),
        "B":np.random.randn(5),
        "C":np.random.randn(5),
        "D":np.random.randn(5),
        "E":np.random.randn(5),
    }
)

结果:
在这里插入图片描述
1、将DataFrame中所有的值保留两位小数显示

df.applymap(lambda x:"%.2f" % x)

结果:
在这里插入图片描述
执行过程:
在这里插入图片描述

三、结合tqdm给apply()过程添加进度条

我们知道apply()在运算时实际上仍然是一行一行遍历的方式,因此在计算量很大时如果有一个进度条来监视运行进度就很舒服。

tqdm:用于添加代码进度条的第三方库

tqdm对pandas也是有着很好的支持。

我们可以使用progress_apply()代替apply(),并在运行progress_apply()之前添加tqdm.tqdm.pandas(desc=‘’)来启动对apply过程的监视。

其中desc参数传入对进度进行说明的字符串,下面我们在上一小部分示例的基础上进行改造来添加进度条功能:

def BMI(series):
    weight = series["weight"]
    height = series["height"]/100
    BMI = weight/height**2
    return BMI
#启动对紧跟着的apply过程的监视
from tqdm import tqdm
tqdm.pandas(desc='apply')
data['BMI'] = data.progress_apply(BMI,axis=1)

结果:
在这里插入图片描述

参考:
https://zhuanlan.zhihu.com/p/396764388
https://zhuanlan.zhihu.com/p/100064394

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐