pandas transform小结

1.transform用法

pandas中的transform是个非常强大的函数。transform可以调用一个函数,在每个组上生成一个相似的索引数据帧,并返回一个数据帧,该数据帧的索引与原始对象的索引相同,并填充转换后的值。核心是在每个组上生成一个相似的索引数据帧,这个就奠定了transform的强大之处,后面很多使用场合中我们都可以慢慢来体会

2.使用transform进行数据标准化

import pandas as pd

category = ['a', 'a', 'a', 'b', 'b', 'c']
score = [80, 85, 90, 70, 76, 64]
data = pd.DataFrame({'category': category, 'score': score})

data['std'] = data['score'].transform(lambda s: (s - s.mean()) / s.std())
print(data)
  category  score       std
0        a     80  0.260785
1        a     85  0.782354
2        a     90  1.303924
3        b     70 -0.782354
4        b     76 -0.156471
5        c     64 -1.408238

上面的代码就是对score列进行标准化操作。

从上面的操作我们可以看出transform的如下几个特征:
1.transform中的函数,执行运算时接收的输入参数是相应的一列数据,因此可以使用诸如mean, std等整体统计指标。
2.最后返回的结果,带上了原始对象的索引,可以很方便的与原始数据进行拼接返回。

3.transform一次传入多个方法

transform还可以一次性传入多个方法,一并进行计算。

import pandas as pd
import numpy as np

category = ['a', 'a', 'a', 'b', 'b', 'c']
score = [80, 85, 90, 70, 76, 64]
data = pd.DataFrame({'category': category, 'score': score})

data[['sqrt', 'std']] = data['score'].transform([np.sqrt, lambda s: (s - s.mean()) / s.std()])
print(data)
  category  score      sqrt       std
0        a     80  8.944272  0.260785
1        a     85  9.219544  0.782354
2        a     90  9.486833  1.303924
3        b     70  8.366600 -0.782354
4        b     76  8.717798 -0.156471
5        c     64  8.000000 -1.408238

4.与groupby配合使用

transform经常与groupby配合使用。下面我们通过一个例子来深刻理解在每个组上生成一个相似的索引数据帧。

我们还是选用计算占比的例子

department = ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C']
group = ['g1', 'g1', 'g2', 'g3', 'g3', 'g4', 'g5', 'g5']
score = [100, 200, 300, 100, 100, 300, 200, 120]
data = pd.DataFrame({'department': department, 'group': group, 'score': score})

下面我们想计算每个group元素在各自department中的占比。

先尝试如下写法

data['rate'] = data['score'] / data.groupby('department')['score'].sum()
print(data)

结果如下

  department group  score        r1  rate
0          A    g1    100  0.070423   NaN
1          A    g1    200  0.140845   NaN
2          A    g2    300  0.211268   NaN
3          B    g3    100  0.070423   NaN
4          B    g3    100  0.070423   NaN
5          B    g4    300  0.211268   NaN
6          C    g5    200  0.140845   NaN
7          C    g5    120  0.084507   NaN

很明显不是我们想要的结果。问题出在哪里?

print(data.groupby('department')['score'].sum())
print(type(data.groupby('department')['score'].sum()))

如果运行上面两行代码,

department
A    600
B    500
C    320
Name: score, dtype: int64
<class 'pandas.core.series.Series'>

很明显上面的结果,与原数据行数不一致,索引也无法对齐,得到的结果都是NaN。
transform就可以完美解决上面的问题。

print(data.groupby('department')['score'].transform('sum'))
print(type(data.groupby('department')['score'].transform('sum')))
0    600
1    600
2    600
3    500
4    500
5    500
6    320
7    320
Name: score, dtype: int64
<class 'pandas.core.series.Series'>

可以看出来,transform保留了与原来数据相同的索引。因此我们求占比,只需要在前面的基础上稍作改动:

data['rate'] = data['score'] / data.groupby('department')['score'].transform('sum')
print(data)

最后输出结果就是我们希望的:

  department group  score      rate
0          A    g1    100  0.166667
1          A    g1    200  0.333333
2          A    g2    300  0.500000
3          B    g3    100  0.200000
4          B    g3    100  0.200000
5          B    g4    300  0.600000
6          C    g5    200  0.625000
7          C    g5    120  0.375000

如果不使用transform,过程就会曲折很多

score_total = data.groupby('department')['score'].sum().rename('score_total').reset_index()
data = data.merge(score_total, on='department')
data['rate'] = data['score'] / data['score_total']

需要先新建一列score_total,然后将score_total与原数据根据department列进行merge(join)操作,最后再计算占比。
相比较之下,transform就简洁方便太多了

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值