【Pandas】【分组操作】

简介

分组操作流程有三:split , apply , combine

首先基于规则把数据拆分成若干组,然后每一组独立使用函数,最后将每一组结果组合在一起

常见apply过程的问题

  • 整合——计算分组的统计量
  • 变换——对分组的每个单元的数据做变换,例如标准化
  • 过滤——按照某些规则筛选一些组

groupby函数

1.按照某一列来分组

a = df.groupby('School')   #按照School列分组

groupby函数会生成一个groupby对象,对象本身不会返回,需要调用其方法才有作用

获得某个school的信息:

a.get_group('S_2').head()

2.按照多列来分组

grouped_mul = df.groupby(['School','Class'])
grouped_mul.get_group(('S_2','C_4'))   #必须对应groupby数目

3.其他调用方法

  • 组容量
a.size()
  • 组数
a.ngroups
  • 遍历groupby对象
for name,group in a:
	print(name)
	display(group.head())

4. 可通过以下代码查看groupby对象可用的函数

print([attr for attr in dir(grouped_single) if not attr.startswith('_')])

5. groupby对象的head和first

  • head函数返回每个组的前k行
a.head(2)  #返回不同学校的前两行
  • first显示以分组为索引的每组的第一个分组信息【等同于head(1)】
a.first()

6. 分组的依据规则

仅需要与被分组数据框长度相同的列表即可,并且支持函数型分组,如下

df.groupby(np.random.choice(['a','b','c'],df.shape[0])).get_group('a').head()

解释:使用np.random.choice随机从abc三个数中找一个生成一个长度为df的长度一致的列表,并按照这个列表进行分组,然后提取属于a组的元素。

df[:5].groupby(lambda x:print(x))

输出:
1101
1102
1103
1104
1105

从代码可以看到,我们利用函数时,传入对象就是索引,因此可以根据这一特性做复杂操作

根据奇偶行分组

df.groupby(lambda x:'奇数行' if not df.index.get_loc(x)%2==1 else '偶数行').groups

输出:
{'偶数行': Int64Index([1102, 1104, 1201, 1203, 1205, 1302, 1304, 2101, 2103, 2105, 2202,
             2204, 2301, 2303, 2305, 2402, 2404],
            dtype='int64', name='ID'),
 '奇数行': Int64Index([1101, 1103, 1105, 1202, 1204, 1301, 1303, 1305, 2102, 2104, 2201,
             2203, 2205, 2302, 2304, 2401, 2403, 2405],
            dtype='int64', name='ID')}

若使用的是多层索引,则lambda表达式中输入为元组

实现的功能为查看两所学校中男女生分别均分是否及格

反例:这里没有使用元组,只会直接返回均分及格均分不及格两组

grouped_score = df.set_index(['Gender','School']).sort_index().groupby(lambda x:'均分及格' if math_score[x].mean()>=60 else '均分不及格')

正例:

grouped_score = df.set_index(['Gender','School']).sort_index().\
            groupby(lambda x:(x,'均分及格' if math_score[x].mean()>=60 else '均分不及格')
for name,_ in grouped_score:print(name)

输出:
(('F', 'S_1'), '均分及格')
(('F', 'S_2'), '均分及格')
(('M', 'S_1'), '均分及格')
(('M', 'S_2'), '均分不及格')

l a m b d a 函 数 中 输 入 了 元 组 , 输 入 的 元 组 s i z e 要 与 设 置 的 i n d e x 数 目 要 一 致 \color{red}{lambda函数中输入了元组,输入的元组size要与设置的index数目要一致} lambdasizeindex

groupby中的[]操作

  • 选出对象的某列或多列的值,不加head还只是一个对象
df.groupby(['Gender','School'])['Math'].head()
df.groupby(['Gender','School'])[['Math','Height']].mean()  #求均值

对连续性变量使用cut函数做分组

bins = [0,40,60,80,90,100]
cuts = pd.cut(df['Math'],bins=bins) #可选label添加自定义标签
df.groupby(cuts)['Math'].count()

聚合(Aggregation)

常用聚合函数

聚合的简单理解就是把一堆数,变成一个标量

一共有这几种的聚合函数mean
countstd标准差var方差size
semdescribefirstsum
lastnth取第n行minmax

同时使用单个或多个聚合函数

group_m = grouped_single['Math']
group_m.std().values
group_m.agg(['sum','mean','std'])

利用元组来重命名

(修改名,原名)

group_m.agg([('rename_sum','sum'),('rename_mean','mean')])

指定哪个函数作用哪个列

Math使用mean和max,Height列使用var

grouped_mul.agg({'Math':['mean','max'],'Height':'var'})

在这里插入图片描述

使用自定义函数

agg函数的传入是分组逐列进行的,有了这个特性就可以做许多事情

grouped_single['Math'].agg(lambda x:print(x.head(),'间隔'))

通过agg可以容易地实现组内极差计算

grouped_single['Math'].agg(lambda x:x.max()-x.min())

NamedAgg函数做多个聚合

grouped_single.agg(min_score1=pd.NamedAgg(column='Math', aggfunc=R1),
                           max_score1=pd.NamedAgg(column='Height', aggfunc='max'),
                           range_score2=pd.NamedAgg(column='Weight', aggfunc=R2)).head()

带参数的聚合函数

def f(s,low,high):
    return s.between(low,high).max()
grouped_single['Math'].agg(f,50,52)
【可无视】使用多个函数,同时至少还带一个参数,wrapper
def f_test(s,low,high):
    return s.between(low,high).max()
def agg_f(f_mul,name,*args,**kwargs):
    def wrapper(x):
        return f_mul(x,*args,**kwargs)
    wrapper.__name__ = name
    return wrapper
new_f = agg_f(f_test,'at_least_one_in_50_52',50,52)
grouped_single['Math'].agg([new_f,'mean']).head()

过滤Filteration

filter函数是用来筛选某些组的(务必记住结果是组的全体),因此传入的值应当是布尔标量

grouped_single[['Math','Physics']].filter(lambda x:(x['Math']>32).all()).head()

all()函数是判断列是否为真,返回布尔值.
grouped_single是以学校名分组,最后是判断每个学校是否符合函数内容,过滤返回

变换Transformation

transform函数中传入的对象是组内的列,并且返回值需要与列长完全一致

grouped_single[['Math','Height']].transform(lambda x:x-x.min()).head()

代码解释:数学和身高会减去自己列的最小值然后替换为这个值

grouped_single[['Math','Height']].transform(lambda x:x.mean()).head()

如果返回了标量值,那么组内的所有元素会被广播为这个值

对组内进行标准化
grouped_single[['Math','Height']].transform(lambda x:(x-x.mean())/x.std()).head()
对组内进行缺失值的均值填充
创建带有空值的df:
df_nan = df[['Math','School']].copy().reset_index()
df_nan.loc[np.random.randint(0,df.shape[0],25),['Math']]=np.nan
df_nan.head()

填充:
df_nan.groupby('School').transform(lambda x: x.fillna(x.mean())).join(df.reset_index()['School']).head()

#因为学校名字是无法求均值的,得到结果是没有School,所以拼接回去

Apply函数

apply函数很灵活,应用广泛,不容易驾驭。

返回值的多样性

  • 标量返回值
df[['School','Math','Height']].groupby('School').apply(lambda x:x.max())
  • 列表返回值
df[['School','Math','Height']].groupby('School').apply(lambda x:x-x.min()).head()
  • 数据框返回值
df[['School','Math','Height']].groupby('School')\
    .apply(lambda x:pd.DataFrame({'col1':x['Math']-x['Math'].max(),
                                  'col2':x['Math']-x['Math'].min(),
                                  'col3':x['Height']-x['Height'].max(),
                                  'col4':x['Height']-x['Height'].min()})).head()
用apply同时统计多个指标

借助OrderedDict工具进行快捷的统计

from collections import OrderedDict
def f(df):
    data = OrderedDict()
    data['M_sum'] = df['Math'].sum()
    data['W_var'] = df['Weight'].var()
    data['H_mean'] = df['Height'].mean()
    return pd.Series(data)
grouped_single.apply(f)

在这里插入图片描述

练习题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值