在日常的数据处理中,经常会对一个 DataFrame
进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的 map
、 apply
和 applymap
可以解决绝大部分这样的数据处理需求。 这篇文章就以 案例 附带 图解 的方式,为大家详细介绍一下这三个方法的 实现原理 ,相信读完本文后,不论是小白还是Pandas的进阶学习者,都会对这三个方法有更深入的理解。
本文演示的数据集是模拟生成的,想练手的可以按下方的代码生成。
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) ] } )
数据集如下所示,各列分别代表身高、体重、是否吸烟、性别、年龄和肤色。
Series数据处理
map
如果需要把数据集中 gender
列的男替换为1,女替换为0,怎么做呢?绝对不是用for循环实现!!!使用 Series.map()
可以很容易做到,最少仅需一行代码。
#①使用字典进行映射 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)
那 map
在实际过程中是怎么运行的呢?请看下面的图解(为了方便展示,仅截取了前10条数据)
不论是利用字典还是函数进行映射, map
方法都是把对应的数据 逐个当作参数 传入到字典或函数中,得到映射后的值。
apply
同时Series对象还有 apply
方法, apply
方法的作用原理和 map
方法类似,区别在于 apply
能够传入功能更为复杂的函数。怎么理解呢?一起看看下面的例子。
假设在数据统计的过程中,年龄 age
列有较大误差,需要对其进行调整(加上或减去一个值),由于这个加上或减去的值 未知 ,故在定义函数时,需要加多一个参数 bias
,此时用 map
方法是操作不了的(传入 map
的函数只能接收一个参数), apply
方法则可以解决这个问题。
def apply_age(x,bias): return x+bias #以元组的方式传入额外的参数 data["age"] = data["age"].apply(apply_age,args=(-3,))
可以看到age列都减了3,当然,这里只是简单举了个例子,当需要进行复杂处理时,更能体现 apply
的作用。
总而言之,对于Series而言, map
可以解决绝大多数的数据处理需求,但如果需要使用较为复杂的函数,则需要用到 apply
方法。
DataFrame数据处理
apply
对 DataFrame
而言, apply
是非常重要的数据处理方法,它可以接收各种各样的函数(Python内置的或自定义的),处理方式很灵活,下面通过几个例子来看看 apply
的具体使用及其原理。
在进行具体介绍之前,首先需要介绍一下 DataFrame
中 axis
的概念,在 DataFrame
对象的大多数方法中,都会有 axis
这个参数,它控制了你指定的操作是沿着0轴还是1轴进行。 axis=0
代表操作对 列columns
进行, axis=1
代表操作对 行row
进行,如下图所示。
如果还不是很了解,没关系,下面会分别对 apply
沿着0轴以及1轴的操作进行讲解,继续往下走。
假设现在需要对 data
中的数值列分别进行 取对数 和 求和 的操作,这时可以用 apply
进行相应的操作,因为是对列进行操作,所以需要指定 axis=0
,使用下面的两行代码可以很轻松地解决我们的问题。
# 沿着0轴求和 data[["height","weight","age"]].apply(np.sum, axis=0) # 沿着0轴取对数 data[["height","weight","age"]].apply(np.log, axis=0)
实现的方式很简单,但调用 apply
时究竟发生了什么呢?过程是怎么实现的?还是通过图解的方式来一探究竟。(取前五条数据为例)
当沿着 轴0(axis=0)
进行操作时,会将各列( columns
)默认以 Series
的形式作为参数,传入到你指定的操作函数中,操作后合并并返回相应的结果。
那如果在实际使用中需要按行进行操作( axis=1
),那整个过程又是怎么实现的呢?
在数据集中,有身高和体重的数据,所以根据这个,我们可以计算每个人的BMI指数(体检时常用的指标,衡量人体肥胖程度和是否健康的重要标准),计算公式是: 体重指数BMI=体重/身高的平方(国际单位kg/㎡)
,因为需要对每个样本进行操作,这里使用 axis=1
的 apply
进行操作,代码如下:
def BMI(series): weight = series["weight"] height = series["height"]/100 BMI = weight/height**2 return BMI data["BMI"] = data.apply(BMI,axis=1)
还是用图解的方式来看看这个过程到底是怎么实现的(以前5条数据为例)。
当 apply
设置了 axis=1
对行进行操作时,会默认将每一行数据以 Series
的形式(Series的索引为列名)传入指定函数,返回相应的结果。
总结一下对 DataFrame
的 apply
操作:
-
当
axis=0
时,对每列columns
执行指定函数;当axis=1
时,对每行row
执行指定函数。 -
无论
axis=0
还是axis=1
,其传入指定函数的默认形式均为Series
,可以通过设置raw=True
传入numpy数组
。 -
对每个Series执行结果后,会将结果整合在一起返回(若想有返回值,定义函数时需要
return
相应的值) -
当然,
DataFrame
的apply
和Series
的apply
一样,也能接收更复杂的函数,如传入参数等,实现原理是一样的,具体用法详见官方文档。
applymap
applymap
的用法比较简单,会对 DataFrame
中的每个单元格执行指定函数的操作,虽然用途不如 apply
广泛,但在某些场合下还是比较有用的,如下面这个例子。
为了演示的方便,新生成一个 DataFrame
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), } ) df
现在想将 DataFrame
中所有的值保留两位小数显示,使用 applymap
可以很快达到你想要的目的,代码和图解如下:
df.applymap(lambda x:"%.2f" % x)
数据处理三板斧就介绍到这里,有问题欢迎下方留言板积极留言呀!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 简单设计落地三板斧
- 线上技术故障处理三板斧
- 互联网架构三板斧之并发
- golang并发三板斧系列之三:context用于退出
- 一线 | 英特尔淘金物联网三板斧:芯片、边缘计算和计算机视觉
- 中国“新三板”——通过大数据实现股转系统监控
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Docker开发指南
[英] Adrian Mouat / 黄彦邦 / 人民邮电出版社 / 2017-4 / 79.00元
Docker容器轻量和可移植的特性尤其适用于动态和分布式的环境,它的兴起给软件开发流程带来了一场革命。本书对Docker进行了全面讲解,包括开发、生产以至维护的整个软件生命周期,并对其中可能出现的一些问题进行了探讨,如软件版本差异、开发环境与生产环境的差异、系统安全问题,等等。一起来看看 《Docker开发指南》 这本书的介绍吧!