一个Python例子,明白apply()和applymap()和map()的学习笔记(1)

首先,这些函数在Series和DataFrame中都能用(除了applymap())

我们来针对一道题目作为例子,来看看这些函数如何使用:
这道题目的例子来源于我看了另外一篇相关的优快云博客,这里附上他的链接:
https://blog.youkuaiyun.com/weixin_39791387/article/details/81487549
题目如下:

df = pd.DataFrame({'change_type' : [1,1,0,0,1,0],
                   'price' : [100, 90, 50, 120, 150, 200],
                   'changed' : [10,8,4,11,14,10]})

在这里插入图片描述
change_type = 1 表示涨价 0表示降价
price 表示经过涨价或者降价之后的价格,也就是 --> 现价
changed 表示 涨了多少 或者 降了多少 是一个绝对值

针对上述表,求:涨降价的比例
首先,先写出计算公式:

涨价比例 = 涨了多少 / 原价
降价的比例 = 降了多少 / 原价

import numpy as np
import pandas as pd
df = pd.DataFrame({'change_type' : [1,1,0,0,1,0],
                   'price' : [100, 90, 50, 120, 150, 200],
                   'changed' : [10,8,4,11,14,10]})
print(df)
print('****************************************************')
#涨价比例   
df_up = df['changed'].div(df['price'].add(df['changed']))
#降价比例
df_down = df['changed'].div(df['price'].sub(df['changed']))

当然你可以直接用 +-*/ 来替换上述的除法div()、加法add()、减法sub()

因为np,pd包的目的就是为了避免写if、for循环,所以我的思路是:用where函数来解决上面的问题

df['scale'] = pd.where(df['change_type'] ==1,df['changed'].div(df['price'].add(df['changed'])),df['changed'].div(df['price'].sub(df['changed'])))
我想这样在 df 新增一列 ‘scale’ 作为比例的结果。

我以为的逻辑是:如果为1,进行涨价比例计算,将结果填入scale列
			 如果为0,进行降价比例计算,将结果填入scale列
			 这样就能直接得到结果了!!!
			 
但是!很遗憾,where并没有帮我们达到这样的要求,这样写会报错!  但是我又不想写if,
查了好多资料,都没有提到关键性的一点。
不好意思,我脑残了。。通过对着python代码的报错情况不断分析!!!终于领悟了为什么!

		where函数在pd和np中的运用还是有区别的:
			pd中:
				是针对单个元素,进行条件判断,然后进行 --> 值替换,
				在这条件判断中用到的'所有数据元素'都会被结果值替换
			np中:
				针对单个列(Series),进行where可以达到我们上述所期望的要求!
				
啊哈哈,虽然能解决了,但是同时能深刻理解where也不错~~
现在我想清楚了一个解决方案了!

下面写上解决思路:
		1、首先在df原表添加一列scale列,你可以用empty()、zero()、arrange()、
		还是手动输入都行,里面的值随便填,因为后续操作要将结果替换进去,
		这里的目的只是为了创建出与'scale列'对应的一列的空间,。
		2、对scale列中的数据,根据条件赋值。
		3、OK问题得到完美解决!!!~下面附上执行结果图。
		
df['scale']=np.arange(6)
df['scale'] = np.where(df['change_type'] == 1, df_up,df_down)
//当然这个条件判断 df['']== 1 有点多此一举,因为0就是False,有值就是True
//可以改为df['scale'] = np.where(df['change_type'], df_up,df_down)
print(df)

在这里插入图片描述

apply()

apply()官方文档
在pd中使用
apply()函数的功能是将一个自定义函数作用于DataFrame的行或者列
(其他骚操作,详细参数,请点击上述官方文档,看官方例子,我这里给出一般用法)

错误案例:

def original_price():
    return np.where(df['change_type'], df_up, df_down)
df['scale'] = np.arrange(6)
df['scale'] = df.apply(original_price())
print(df)
这里我定义了一个函数,然后将函数写入apply参数中,
但是报错了,不知道为什么,希望懂得大佬能留言指导一下,谢谢!



我自己的解决方案是:

def original_price():
    return np.where(df['change_type'], df_up, df_down)
df['scale']=np.arange(6)
df['scale'] = df.apply(lambda x: np.where(df['change_type'] == 1, df_up,df_down))
print(df)
添加一个lambda,写成lambda表达式就能解决原因,

在这里插入图片描述


但是这样写还不如直接写成:
df['scale'] = df.apply(lambda x: np.where(df['change_type'], df_up, df_down))
这样更符合lambda表达式的初衷,(里面的形参x可以不填,因为没用到)
但是查阅了lambda表达式资料,我也没明白如何解决上述错误的原因,
只看到lambda是一个匿名函数,它可以当做变量使用,在这里应该就是这个意思,
希望懂得的大佬能指点一下!


所以综上,
		我自己理解的apply()方法的一般用法,
		是在里面传入一个lambda表达式,
		这样绝对不会报错!
		
		还有重要的一点,要留意当心 apply中的 axis参数,
		因为实际处理结果和我们认为的相反,可以多试试去注意一下!

在np中使用:

np中没有apply这个方法,
但是你输入np.a的时候,会自动跳出来一个 np.apply_along_axis方法。
没错!
我仔细看了一下里面的形参,需要传入3个参数:
									func:lambda表达式绝对不会报错
									axis=轴(填0或者‘index’表示行
											填1或者‘columns’表示列)
									arr=填你要进行操作的Series对象


解决方案:
df02 = np.apply_along_axis(lambda x:np.where(df['change_type'],df_up,df_down),axis=0,arr=df['change_type'])
print(df02)

在这里插入图片描述

细看了下,还有个np.apply_over_axex()方法,
		它针对的主要是高维数组,如(3维)数组上的操作,
		官方文档:
		https://docs.scipy.org/doc/numpy-1.12.0/reference/generated/numpy.apply_over_axes.html
		看不懂的话可以看下面这个优快云大佬的链接:
		https://blog.csdn.net/a_31415926/article/details/50491211

map()

map()菜鸟教程
map()和reduce()用法和原理
map() 是python自带的函数,也就是我们常说的高阶函数,但它在DataFrame中可以直接使用 .map() 后缀的方式调用,由于只能直接对序列元素的操作,所以必须对DataFrame的某列 (只针对于列) 应用操作。
在pd中使用:

解决方案:

df03 = df['change_type'].map(lambda x:np.where(df['change_type'],df_up,df_down))[0]
print(df03)
因为map操作的是序列,所以是对df['change_type']这一列进行.map()

在这里插入图片描述
在np中使用:

直接对np数组对象.map()就行了
比如:
	我先拷贝一列DataFrame列赋值给变量data01,这样data01就是一个Series对象
	然后对Series对象进行操作
	当然这对于解决这道题目多此一举,这里只是演示np如何用map()

data01 = df['change_type']
data02 = df['price']
data03 = df['changed']

df04 = data01.map(lambda x:np.where(data01,df_up,df_down))[0]
print(df04)

applymap()

applymap()官方文档
只能在pd中使用:
因为Series对象没有applymap()方法

解决方案:
df05 = df.applymap(lambda x:np.where(df['change_type'],df_up,df_down))['change_type'][0]
print(df05)

在这里插入图片描述

最后来看一下3种方法在DataFrame种的区别演示

原始数据:
在这里插入图片描述
apply():

df01 = df.apply(lambda x:np.where(df['change_type'],df_up,df_down))

三列数据一致,原因是where方法不恰当运用导致的,这里可以忽略。
体会一下3种方法,导致的结果形式即可。
在这里插入图片描述
map():

df03 = df['change_type'].map(lambda x:np.where(df['change_type'],df_up,df_down))
print(df03)

返回的是一个Series,也就是一列,一列当中的每一行结果都重复。
可以df[ ‘xxx’ ].map(xxxxx)[0] 通过索引取值获得一行,作为结果值。
在这里插入图片描述
applymap():

df05 = df.applymap(lambda x:np.where(df['change_type'],df_up,df_down))
print(df05)

返回的是一个DataFrame,也就是有三列,
因为applymap()不恰当使用,导致了change_type列 和 price列 和 changed列 的值都一样了。
大致意会一下三种方法返回的形式即可
在这里插入图片描述

总结

apply()和map()和applymap()
三种方法的本质,其实是对什么type的对象操作,返回对应type的结果。
apply()官方文档
apply_along_axis官方文档
apply_over_axes()官方文档

(详细参数,请点击上述官方文档,看官方例子,我这里给出一般用法总结)

apply():
	pandas中的方法:
				  DataFrame操作,返回DataFrame
	numpy中无此方法:
				  但是有类似的2个方法,apply_along_axis和apply_over_axes
				  
	还有重要的一点,要留意当心 apply中的 axis参数,
		因为实际处理结果和我们认为的相反,可以多试试去注意一下!

map()菜鸟教程
map()和reduce()用法和原理

map():
	python自带的函数(高阶函数):
				  只对序列进行操作,在pandas和numpy中可以理解为只对Series操作

applymap()官方文档

applymap():
	pandas中的方法:
				  对DataFrame操作,返回DataFrame

where()方法
where()官方文档
官方文档还是不理解的话,看这篇博客试试
另外一篇

1、 where在pandas和numpy中的用法  小区别:
	   pandas中:
				//条件为真不做修改,条件为假替换成相应值
				//false_value不填默认为np.nan,即显示:NaN(Not a number)
				
				df.where(conditon,false_value)  
				
				//mask()方法和where作用相反,条件为真做修改,条件为假不修改
				//true_value不填默认为np.nan,即显示:NaN(Not a number)
				
				df.mask(condition,true_value)
				
	   numpy中:
				//根据条件判断,如果为True替换成相应值,如果为False替换成相应值
				arr.where(condition,true_value,false_value)
				
2、	where函数在pd和np中的运用的   注意点:
		pd中:
			是针对单个元素,进行条件判断,然后进行 --> 值替换,
			在这条件判断中用到的(所有数据元素)都会被结果值替换。
		np中:
			针对单个要显示判断结果的列(Series),进行where方法判断,
			此时条件判断中用到的(所有数据元素)都不会被修改。

lambda表达式(匿名函数):
lambda表达式详解
lambda表达式用的时候需要的一个注意点

匿名函数,可以当参数调用

、、哭了。。。。。。。我这个菜B花了一下午,终于把这篇博客写完了。。。现在脑子一片浆糊QAQ。。。。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值