pandas_day04

4.1分组模式及其对象
如,依据性别分组,统计全国人口寿命的平均值
要想实现分组操作,必须明确3个要素:分组依据、数据来源、操作及其返回结果

import pandas as pd
import numpy as np
df = pd.read_csv('learn_pandas.csv')
# 按照性别统计身高中位数
df.groupby('Gender')['Height'].median()
Gender
Female    159.6
Male      173.4
Name: Height, dtype: float64

4.1.2 分组依据的本质
genuine多个维度进行分组,只需在groupby中传入响应列名构成列表即可

df.groupby(['School','Gender'])['Height'].mean()
School                         Gender
Fudan University               Female    158.776923
                               Male      174.212500
Peking University              Female    158.666667
                               Male      172.030000
Shanghai Jiao Tong University  Female    159.122500
                               Male      176.760000
Tsinghua University            Female    159.753333
                               Male      171.638889
Name: Height, dtype: float64
# 根据学生体重是否超过总体均值来分组
# 先在变量中定义条件,然后传到()中进行条件筛选
condition = df.Weight > df.Weight.mean()
df.groupby(condition)['Height'].mean()
Weight
False    159.034646
True     172.705357
Name: Height, dtype: float64

练一练,根据上下四位数分割,将体重分为high、normal、low三组,统计身高的平均值

df.groupby(condition)['Height'].mean()
low = df['Weight']<df['Weight'].quantile(1/3)
df.groupby(low)['Height'].mean()
Weight
False    167.085484
True     155.089831
Name: Height, dtype: float64
high = df['Weight'] > df['Weight'].quantile(2/3)
df.groupby(high)['Height'].mean()
Weight
False    159.034646
True     172.705357
Name: Height, dtype: float64
norm = df['Weight'] < (df['Weight'].quantile(2/3))
df.groupby(norm)['Height'].mean() 
Weight
False    171.245714
True     158.245133
Name: Height, dtype: float64

从索引可以看出,最后产生的结果是按照条件列表中元素的值(True or False)来分组

item = np.random.choice(list('abc'), df.shape[0])
df.groupby(item)['Height'].mean()
a    164.115517
b    162.449180
c    163.137500
Name: Height, dtype: float64
# 传入多个序列,分组的依据就是这两个序列对应行的唯一组合
# 因为condition是一个判断条件,所以返回的只有True和False两个值
# 相当于传入的是一个或多个列,最后分组的依据来源于组合的unique值
# 用drop_duplicates就能知道具体的组类别
df.groupby([condition, item])['Height'].mean()
Weight   
False   a    159.323684
        b    159.144444
        c    158.672727
True    a    173.220000
        b    171.743750
        c    172.960000
Name: Height, dtype: float64

4.1.3 groupby对象

gb = df.groupby(['School', 'Grade'])
gb
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000227FAC8E2E8>
# ngroups可以访问分为了多少组
gb.ngroups
16
# groups 可以返回从组名映射到组索引列表的字典
# 使用groups之后,可以和python的字典一样的用法
res = gb.groups
res.keys()
res.values()
res
{('Fudan University', 'Freshman'): [15, 28, 63, 70, 73, 105, 108, 157, 186], ('Fudan University', 'Junior'): [26, 41, 82, 84, 90, 107, 145, 152, 173, 187, 189, 195], ('Fudan University', 'Senior'): [39, 46, 49, 52, 66, 77, 112, 129, 131, 138, 144], ('Fudan University', 'Sophomore'): [3, 4, 37, 48, 68, 98, 135, 170], ('Peking University', 'Freshman'): [1, 32, 35, 36, 38, 45, 54, 57, 88, 96, 99, 140, 185], ('Peking University', 'Junior'): [9, 20, 59, 72, 75, 102, 159, 183], ('Peking University', 'Senior'): [30, 86, 116, 127, 130, 132, 147, 194], ('Peking University', 'Sophomore'): [29, 61, 83, 101, 120], ('Shanghai Jiao Tong University', 'Freshman'): [0, 6, 10, 60, 114, 117, 119, 121, 141, 148, 149, 153, 184], ('Shanghai Jiao Tong University', 'Junior'): [31, 42, 50, 56, 58, 64, 85, 93, 115, 122, 143, 155, 164, 172, 174, 188, 190], ('Shanghai Jiao Tong University', 'Senior'): [2, 12, 19, 21, 22, 23, 79, 87, 89, 103, 104, 109, 123, 134, 156, 161, 165, 166, 171, 192, 197, 198], ('Shanghai Jiao Tong University', 'Sophomore'): [13, 65, 71, 124, 167], ('Tsinghua University', 'Freshman'): [5, 8, 33, 34, 43, 44, 47, 51, 62, 67, 81, 111, 125, 133, 136, 142, 146], ('Tsinghua University', 'Junior'): [7, 11, 16, 17, 27, 69, 94, 95, 113, 118, 128, 137, 150, 154, 158, 160, 162, 163, 169, 176, 177, 191], ('Tsinghua University', 'Senior'): [14, 18, 24, 25, 78, 92, 100, 126, 168, 175, 179, 180, 193, 196], ('Tsinghua University', 'Sophomore'): [40, 53, 55, 74, 76, 80, 91, 97, 106, 110, 139, 151, 178, 181, 182, 199]}

上一节提到过可以用drop_duplicates就能知道具体的组类别,可以用groups属性完成类似的功能

df.groupby(['School','Gender']).groups.keys()
dict_keys([('Fudan University', 'Female'), ('Fudan University', 'Male'), ('Peking University', 'Female'), ('Peking University', 'Male'), ('Shanghai Jiao Tong University', 'Female'), ('Shanghai Jiao Tong University', 'Male'), ('Tsinghua University', 'Female'), ('Tsinghua University', 'Male')])

当size作为DataFrame的属性时,返回的是表长乘以表宽的大小,但在groupby对象上表示统计每个组的元素个数

# 最后一列表示每个组的元素个数
gb.size()
School                         Grade    
Fudan University               Freshman      9
                               Junior       12
                               Senior       11
                               Sophomore     8
Peking University              Freshman     13
                               Junior        8
                               Senior        8
                               Sophomore     5
Shanghai Jiao Tong University  Freshman     13
                               Junior       17
                               Senior       22
                               Sophomore     5
Tsinghua University            Freshman     17
                               Junior       22
                               Senior       14
                               Sophomore    16
dtype: int64
# get_group 方法可以直接获取所在组对应的行,此时需要知道组的具体名字
# 只取前3列,和前3行
gb.get_group(('Fudan University', 'Freshman')).iloc[:3, :3]
SchoolGradeName
15Fudan UniversityFreshmanChangqiang Yang
28Fudan UniversityFreshmanGaoqiang Qin
63Fudan UniversityFreshmanGaofeng Zhao

4.1.4 分组的三大操作

  1. 依据性别分组,统计全国人口寿命的平均值 —> 每一个组返回一个标量值,可以是平均值、中位数、组容量size等
  2. 依据季节分组,对每一个季节的温度进行组内标准化 —> 做了原序列的标准化处理,也就是说每组返回的是一个Series类型
  3. 依据班级分组,筛选出组内数学分数的平均值超过80分的班级 —> 既不是标量也不是序列,返回整个组所在行的本身,即返回了DataFrame类型4.2 聚合函数
    4.2.1 内置聚合函数
    一些定义在groupby对象的聚合函数,它的速度基本都会经过内部的优化,使用功能应当优先考虑
    根据返回标量值的原则,包括:max/min/mean/median/count/ all/any/idxmax/idxmin/mad/nunique/skew/quantile/sum/std/var/sem/size/prod
gb = df.groupby('Gender')['Height']
gb.idxmin()
Gender
Female    143
Male      199
Name: Height, dtype: int64
gb.quantile(0.95)
Gender
Female    166.8
Male      185.9
Name: Height, dtype: float64
# 聚合函数当传入的数据来源包含多个列时,将按照列进行迭代计算
gb = df.groupby('Gender')[['Height','Weight']]
gb.max()
HeightWeight
Gender
Female170.263.0
Male193.989.0

4.2.2 agg方法
可以解决如下4个问题:
1).无法同时使用多个函数
2).无法对特定的列使用特定的聚合函数
3).无法使用自定义的聚合函数
4).无法直接对结果的列名在聚合前进行自定义命名

# 为解决问题1)
# 列索引是多级索引,第一层是数据源,第二层为使用的聚合方法,分别逐一对列使用聚合,因此结果有6列
gb.agg(['sum','idxmax','skew'])
HeightWeight
sumidxmaxskewsumidxmaxskew
Gender
Female21014.028-0.2192536469.028-0.268482
Male8854.91930.4375353929.02-0.332393
# 为解决问题2)
# 对于方法和列的特殊对应,可以通过构造字典传入agg中实现,其中字典以列名为键,以聚合字符串或字符串列表为值
gb.agg({'Height':['mean','max'],'Weight':'count'})
HeightWeight
meanmaxcount
Gender
Female159.19697170.2135
Male173.62549193.954

请使用2)中传入字典的方法,完成1)中等价的聚合任务

gb.agg({'Height':['sum','idxmax','skew'],'Weight':['sum','idxmax','skew']})
HeightWeight
sumidxmaxskewsumidxmaxskew
Gender
Female21014.028-0.2192536469.028-0.268482
Male8854.91930.4375353929.02-0.332393

3)使用自定义函数
在agg中可以使用具体的自定义函数,需要注意传入函数的参数是之前数据源中的列,逐列进行计算

# 分组计算身高和体重的极差
gb.agg(lambda x: x.mean()-x.min())
HeightWeight
Gender
Female13.7969713.918519
Male17.9254921.759259

在groupby对象中可以使用describe方法进行统计信息汇总,请同时使用多个聚合函数,完成与该方法相同的功能

gb.describe()
HeightWeight
countmeanstdmin25%50%75%maxcountmeanstdmin25%50%75%max
Gender
Female132.0159.196975.053982145.4155.675159.6162.825170.2135.047.9185195.40598334.044.048.052.0063.0
Male51.0173.625497.048485155.7168.900173.4177.150193.954.072.7592597.77255751.069.073.078.7589.0
gb.agg(['count','mean','std','min',('25%', lambda x: x.quantile(0.25)), ('50%', lambda x: x.quantile(0.5)),('75%', lambda x:x.quantile(0.75)),'max'])
HeightWeight
countmeanstdmin25%50%75%maxcountmeanstdmin25%50%75%max
Gender
Female132159.196975.053982145.4155.675159.6162.825170.213547.9185195.40598334.044.048.052.0063.0
Male51173.625497.048485155.7168.900173.4177.150193.95472.7592597.77255751.069.073.078.7589.0

由于传入的是序列,因此序列上的方法和属性都是可以在函数中使用的,只需保证返回值是标量即可
如果组的指标均值超过该指标的总体均值,返回high,否则返回low

def my_func(s):
    res  = 'Hight'
    if s.mean() <= df[s.name].mean():
        res = 'Low'
    return res
gb.agg(my_func)
HeightWeight
Gender
FemaleLowLow
MaleHightHight
  1. 聚合结果重命名
    需要对上述函数的位置改写为元组,元组的第一个元素为新的名字,第二个位置为原来的函数,包括聚合字符串和自定义函数
gb.agg([('range', lambda x:x.max()-x.min()), ('my_sum','sum')])
HeightWeight
rangemy_sumrangemy_sum
Gender
Female24.821014.029.06469.0
Male38.28854.938.03929.0
# 使用对一个或多个列使用单个聚合的时候,重命名需要加方括号,否则就不知道是新的名字函数手误输错的内置函数字符串
gb.agg([('my_sum', 'sum')])
HeightWeight
my_summy_sum
Gender
Female21014.06469.0
Male8854.93929.0
gb.agg({'Height':[('my_func', my_func),'sum'],'Weight':[('range', lambda x:x.max())]})
HeightWeight
my_funcsumrange
Gender
FemaleLow21014.063.0
MaleHight8854.989.0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值