新闻动态

分享Pandas库中的一些宝藏函数transform()

发布日期:2022-01-29 13:33 | 文章来源:源码之家

Pandas函数的核心功能是,既计算了统计值,又保留了明细数据。为了更好地理解transform和agg的不同,下面从实际的应用场景出发进行对比。

aggregation会返回数据的缩减版本,而transformation能返回完整数据的某一变换版本供我们重组。这样的transformation,输出的形状和输入一致。一个常见的例子是通过减去分组平均值来居中数据。

#数据构造
data = pd.DataFrame(
{"company":['百度', '阿里', '百度', '阿里', '百度', '腾讯', '腾讯', '阿里', '腾讯', '阿里'],
"salary":[43000, 24000, 40000, 39000, 8000, 47000, 25000, 16000, 21000, 38000],
"age":[25, 34, 49, 42, 28, 23, 45, 21, 34, 29]}) 
data
  company  salary  age
0百度4300025
1阿里2400034
2百度4000049
3阿里3900042
4百度 800028
5腾讯4700023
6腾讯2500045
7阿里1600021
8腾讯2100034
9阿里3800029

1、transform作用于Series

1)单个变换函数

当transform作用于单列Series时较为简单 ,对salary列进行transform变换我们可以传入任意的非聚合类函数,比如对工资列对数化

import pandas as pd 
import numpy  as np
# 对工资对数化
data['salary'].transform(np.log) 
0 10.668955
1 10.085809
2 10.596635
3 10.571317
4  8.987197
5 10.757903
6 10.126631
7  9.680344
8  9.952278
9 10.545341
Name: salary, dtype: float64

除了内置函数,还可以传入lambda函数

# lambda函数
data['salary'].transform(lambda s: s+1)
0 43001
1 24001
2 40001
3 39001
4  8001
5 47001
6 25001
7 16001
8 21001
9 38001
Name: salary, dtype: int64

2)多个变换函数

也可以传入包含多个变换函数的列表来一口气计算出多列结果:

data['salary'].transform([np.log, lambda s: s+1, np.sqrt])
log  <lambda>  sqrt
0  10.668955  43001  207.364414
1  10.085809  24001  154.919334
2  10.596635  40001  200.000000
3  10.571317  39001  197.484177
48.987197800189.442719
5  10.757903  47001  216.794834
6  10.126631  25001  158.113883
79.680344  16001  126.491106
89.952278  21001  144.913767
9  10.545341  38001  194.935887

而又因为transform传入的函数,在执行运算时接收的输入参数是对应的整列数据,所以我们可以利用这个特点实现诸如数据标准化、归一化等需要依赖样本整体统计特征的变换过程:

# 利用transform进行数据标准化
data['salary'].transform(lambda s: (s - s.mean()) / s.std())
0 0.991038
1-0.468630
2 0.760564
3 0.683739
4-1.697825
5 1.298337
6-0.391806
7-1.083228
8-0.699104
9 0.606915
Name: salary, dtype: float64

2、 transform作用于DataFrame

当transform作用于整个DataFrame时,实际上就是将传入的所有变换函数作用到每一列中:

data.loc[:,'salary':'age'].transform(lambda s:(s-s.mean()) /s.std())
  salary age
0  0.991038 -0.832050
1 -0.468630  0.104006
2  0.760564  1.664101
3  0.683739  0.936057
4 -1.697825 -0.520031
5  1.298337 -1.040063
6 -0.391806  1.248075
7 -1.083228 -1.248075
8 -0.699104  0.104006
9  0.606915 -0.416025

而当传入多个变换函数时,对应的返回结果格式类似agg中的机制,会生成MultiIndex格式的字段名

data.loc[:, 'salary': 'age'].transform([np.log, lambda s: s+1])
  salary age
log <lambda> log <lambda>
0  10.668955 43001  3.218876 26
1  10.085809 24001  3.526361 35
2  10.596635 40001  3.891820 50
3  10.571317 39001  3.737670 43
48.987197  8001  3.332205 29
5  10.757903 47001  3.135494 24
6  10.126631 25001  3.806662 46
79.680344 16001  3.044522 22
89.952278 21001  3.526361 35
9  10.545341 38001  3.367296 30

而且由于作用的是DataFrame,还可以利用字典以键值对的形式,一口气为每一列配置单个或多个变换函数:

(data.loc[:, 'salary': 'age']
.transform({'age': lambda s: (s - s.mean()) / s.std(),
 'salary': [np.log, np.sqrt]}))
age  salary
<lambda>  log  sqrt
0 -0.832050  10.668955  207.364414
1  0.104006  10.085809  154.919334
2  1.664101  10.596635  200.000000
3  0.936057  10.571317  197.484177
4 -0.5200318.98719789.442719
5 -1.040063  10.757903  216.794834
6  1.248075  10.126631  158.113883
7 -1.2480759.680344  126.491106
8  0.1040069.952278  144.913767
9 -0.416025  10.545341  194.935887

3、transform作用于groupby分组后

在原来的数据中,我们知道了如何求不同公司的平均薪水,假如需要在原数据集中新增一列salary_mean,代表该公司的平均薪水,该怎么实现呢?

data['salary_mean'] = data.groupby('company')[['salary']].transform('mean')
data 
  company  salary  agesalary_mean
0百度4300025  30333.333333
1阿里2400034  29250.000000
2百度4000049  30333.333333
3阿里3900042  29250.000000
4百度 800028  30333.333333
5腾讯4700023  31000.000000
6腾讯2500045  31000.000000
7阿里1600021  29250.000000
8腾讯2100034  31000.000000
9阿里3800029  29250.000000

通过上面的数据可以看出,利用transform输出既得到了统计数据,形状也没有变化。

当然,也可对多个数据列进行计算

data.groupby('company')[['salary', 'age']].transform('mean')
salaryage
0  30333.333333  34.0
1  29250.000000  31.5
2  30333.333333  34.0
3  29250.000000  31.5
4  30333.333333  34.0
5  31000.000000  34.0
6  31000.000000  34.0
7  29250.000000  31.5
8  31000.000000  34.0
9  29250.000000  31.5

我们也可以用map函数实现类似的功能,但是稍微复杂点,但是有助于我们理解transform的含义。

avg_dict = data.groupby('company')['salary'].mean().to_dict()
avg_dict#得到了一个平均工资的字典
{'百度': 30333.333333333332, '腾讯': 31000.0, '阿里': 29250.0}
#利用map函数,将得到的字典映射到对应的列
data['salary_mean'] = data['company'].map(avg_dict)
data
company  salary  agesalary_mean
0百度4300025  30333.333333
1阿里2400034  29250.000000
2百度4000049  30333.333333
3阿里3900042  29250.000000
4百度 800028  30333.333333
5腾讯4700023  31000.000000
6腾讯2500045  31000.000000
7阿里1600021  29250.000000
8腾讯2100034  31000.000000
9阿里3800029  29250.000000

以图解的方式来看看进行groupby后transform的实现过程(公司列包含ABC,salary列为每个员工的工资明细):

上图中的大方框是transform和agg 所不一样的地方,对agg而言,会计算并聚合得到 A,B,C 公司对应的均值并直接返回,每个公司一条数据,但对transform而言,则会对每一条数据求得相应的结果,同一组内的样本会有相同的值,组内求完均值后会按照原索引的顺序返回结果。

以上就是分享Pandas中的一些宝藏函数transform()的详细内容,更多关于Pandas函数transform()的资料请关注本站其它相关文章!

海外服务器租用

版权声明:本站文章来源标注为YINGSOO的内容版权均为本站所有,欢迎引用、转载,请保持原文完整并注明来源及原文链接。禁止复制或仿造本网站,禁止在非www.yingsoo.com所属的服务器上建立镜像,否则将依法追究法律责任。本站部分内容来源于网友推荐、互联网收集整理而来,仅供学习参考,不代表本站立场,如有内容涉嫌侵权,请联系alex-e#qq.com处理。

相关文章

实时开通

自选配置、实时开通

免备案

全球线路精选!

全天候客户服务

7x24全年不间断在线

专属顾问服务

1对1客户咨询顾问

在线
客服

在线客服:7*24小时在线

客服
热线

400-630-3752
7*24小时客服服务热线

关注
微信

关注官方微信
顶部