第十四篇,数据分析之pandas的分组运算其二

分组对象的运算方法

下面以一个分组对象的方法为例,实现对指定列的数据的运算。

a = pd.DataFrame({'student':['math','chinese','english','math','english','chinese'],
                  'number':[89,98,78,96,65,100]})
a['teacher'] = ['java','html','python','java','python','python']
a['money'] = [10,20,30,40,50,60]
print(a.groupby('teacher')['number'].describe())
         count  mean        std   min    25%   50%    75%    max
teacher                                                         
html       1.0  98.0        NaN  98.0  98.00  98.0  98.00   98.0
java       2.0  92.5   4.949747  89.0  90.75  92.5  94.25   96.0
python     3.0  81.0  17.691806  65.0  71.50  78.0  89.00  100.0

可以看出来,以上代码规定了describe()只计算a[‘number’]列的数据,可以看出来describe还是得到了很多的统计量,如果不需要这么多,或者需要的没有,比如同时显示标准差跟和,那也没有其他的方法,当然有,Pandas为此提供了一些专门的方法:aggregate(),apply(),filter(),transform(),注意他们都是分组对象的方法,都以分组对象为单位进行计算。

aggregate()
aggregate函数的作用是可以将若干个用于统计运算的函数聚合到一起:

aggregate(func, axis=0, *args, **kwargs) 
print(a)
print('='*30)
print(a.groupby('teacher').aggregate(['mean','min','max']))
   student  number teacher  money
0     math      89    java     10
1  chinese      98    html     20
2  english      78  python     30
3     math      96    java     40
4  english      65  python     50
5  chinese     100  python     60
==============================
        number               money        
          mean min  max       mean min max
teacher                                   
html      98.0  98   98  20.000000  20  20
java      92.5  89   96  25.000000  10  40
python    81.0  65  100  46.666667  30  60

以上函数,将平均数,最小值,最大值三个计算函数聚合在一起,让他们分别对三个分组对象中的数据进行相应的计算。是‘number’列的最大值分别是html,java,python这三个分组中各自的最大值,不是所有数据的最大值,如果aggregate的参数是一个函数对象跟多个函数组成的列表有什么区别如下:

print(a.groupby('teacher').aggregate(np.mean))
print(a.groupby('teacher').mean())
         number      money
teacher                   
html       98.0  20.000000
java       92.5  25.000000
python     81.0  46.666667
         number      money
teacher                   
html       98.0  20.000000
java       92.5  25.000000
python     81.0  46.666667

当然如果是一个函数对象的话,用后面那个方法更简单,这里只是提一下,aggregate()也可以缩写成agg(),这个方法还可以对不同的列进行不同的运算,就是使用字典形式建立列标签和函数对象:

print(a.groupby('teacher').aggregate({'number':np.mean,'money':np.mean}))
print(a.groupby('teacher').aggregate({'number':['mean','min','max']}))
         number      money
teacher                   
html       98.0  20.000000
java       92.5  25.000000
python     81.0  46.666667
        number         
          mean min  max
teacher                
html      98.0  98   98
java      92.5  89   96
python    81.0  65  100

自行领会,轴的方向也是可以改变的默认axis=0
filter()
filter()有筛选的意思,具体怎么筛选,筛选谁可以查看帮助文档:

filter(items=None, like=None, regex=None, axis=None)

下面我们就来写个filter方法:

a = pd.DataFrame({'student':['math','chinese','english','math','english','chinese'],
                  'number':[89,98,78,96,65,100]})
a['teacher'] = ['java','html','python','java','python','python']
a['money'] = [10,20,30,40,50,60]
print(a)
print(a.groupby('teacher').mean())
def high_money(x):
    return x['money'].mean() > 30
print(a.groupby('teacher').filter(high_money))            
   student  number teacher  money
0     math      89    java     10
1  chinese      98    html     20
2  english      78  python     30
3     math      96    java     40
4  english      65  python     50
5  chinese     100  python     60

         number      money
teacher                   
html       98.0  20.000000
java       92.5  25.000000
python     81.0  46.666667

   student  number teacher  money
2  english      78  python     30
4  english      65  python     50
5  chinese     100  python     60

可以看出def high_money()这个函数返回值是布尔值,计算money列里面数据的平均值判断是否大于30,大于的就返回True,否则就False,filter()以True为依据将teacher列内符合的数据以DataFrame的方式返回,False的则不返回,最后将返回的分组数据组合输出,filter()所筛选的对象是以分组对象为单位的,如果符合条件,则分组数据全部返回,而不是逐条筛选。
transform()
aggregate()指定针对分组对象运算的函数,得到的结果为分组对象各自运算结果的集合,此结果与原数据相比,不论是数据量还是行列标签索引都发生的变换;filter()根据分组对象设置的条件对本分组对象中的数据进行筛选,最终将得到的数据合并返回,这个返回结果一般比原数据少。相比而言,transfrom()的作用仅仅是改变了原数据的值,返回值的长度与原数据相同,这里返回值相对原数据不是原地修改,而是生成了一个新的对象。

transform(func, axis=0, *args, **kwargs)
print(a.groupby('teacher').transform(lambda x:x-x.mean()))

   number      money
0    -3.5 -15.000000
1     0.0   0.000000
2    -3.0 -16.666667
3     3.5  15.000000
4   -16.0   3.333333
5    19.0  13.333333

这个我们可以好好看看之前那个filter的案例,仔细做对比,可以观察到传给transform()函数对象的lambda x:x-x.mean()是对每个分组进行计算的,上面那个列子中,以math,分组为例,这个分组中“number”列的平均值为92.5,然后这种数值有两个,分别是89和96,这两个数分别减去92.5,就得到为我们上面的数据。
apply()
apply()相比前面的更加灵活,

apply(func, axis=0, broadcast=None, raw=False, reduce=None, result_type=None, args=(), **kwds)
def money_mean(x):
    x['money_mean'] = x['number'] * x['money'].mean()
    return x
print(a.groupby('teacher')['money'].mean())
print(a.groupby('teacher').apply(money_mean))
teacher
html      20.000000
java      25.000000
python    46.666667
Name: money, dtype: float64
   student  number teacher  money   money_mean
0     math      89    java     10  2225.000000
1  chinese      98    html     20  1960.000000
2  english      78  python     30  3640.000000
3     math      96    java     40  2400.000000
4  english      65  python     50  3033.333333
5  chinese     100  python     60  4666.666667

上面操作,目的在于增加一列,这列按照money_mean()函数进行计算,例如将java的两个money元素相加乘以它相对应的number,有两个java分别是89和96,与他们相乘得到的结果写入money_mean列里面。
最后,在所有对数值进行的计算中,数据为字符串的列自动不参与计算,比如student列或者teacher列,尽管我们没有声明,这就是Pandas的智能之处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值