datawhale的pandas学习第四章 分组

本文详细介绍了Pandas库中数据分组的概念和操作,包括分组模式、分组依据的本质、Groupby对象、聚合函数、变换和过滤等。通过实例解析了如何使用分组进行数据统计、计算和筛选,以及跨列分组的apply方法。文章还提供了多个练习题以巩固读者的理解。
摘要由CSDN通过智能技术生成

导入本章所需模块:

import numpy as np
import pandas as pd

一、分组模式及其对象

1. 分组的一般模式

分组操作在日常生活中使用极其广泛,例如:

  • 依据性别性别分组,统计全国人口寿命寿命的平均值平均值
  • 依据季节季节分组,对每一个季节的温度温度进行组内标准化组内标准化
  • 依据班级班级筛选出组内数学分数数学分数的平均值超过80分的班级

从上述的几个例子中不难看出,想要实现分组操作,必须明确三个要素:分组依据分组依据、数据来源数据来源、操作及其返回结果操作及其返回结果。同时从充分性的角度来说,如果明确了这三方面,就能确定一个分组操作,从而分组代码的一般模式即:

df.groupby(分组依据)[数据来源].使用操作

例如第一个例子中的代码就应该如下:

df.groupby('Gender')['Longevity'].mean()

现在返回到学生体测的数据集上,如果想要按照性别统计身高中位数,就可以如下写出:

在这里插入图片描述

2. 分组依据的本质

前面提到的若干例子都是以单一维度进行分组的,比如根据性别,如果现在需要根据多个维度进行分组,该如何做?事实上,只需在groupby中传入相应列名构成的列表即可。例如,现想根据学校和性别进行分组,统计身高的均值就可以如下写出:

在这里插入图片描述

目前为止,groupby的分组依据都是直接可以从列中按照名字获取的,那如果想要通过一定的复杂逻辑来分组,例如根据学生体重是否超过总体均值来分组,同样还是计算身高的均值。

首先应该先写出分组条件:

在这里插入图片描述

【练一练1】

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

【解答】
df_copy=df.copy()
df_copy['group_Weight']=df['Weight'].mask(df['Weight']>=df['Weight'].quantile(0.75),'high').mask(
    df['Weight']<df['Weight'].quantile(0.25),'low').mask((df['Weight']<df['Weight'].quantile(0.75))&(df['Weight']>=df['Weight'].quantile(0.25)),'normal')

df_copy.groupby('group_Weight')['Height'].mean()
group_Weight
high      174.511364
low       153.753659
normal    161.800000
Name: Height, dtype: float64
【END】

从索引可以看出,其实最后产生的结果就是按照条件列表中元素的值(此处是TrueFalse)来分组,下面用随机传入字母序列来验证这一想法:

item = np.random.choice(list('abc'), df.shape[0])
df.groupby(item)['Height'].mean()
a    162.008621
b    162.625000
c    164.844615
Name: Height, dtype: float64

此处的索引就是原先item中的元素,如果传入多个序列进入groupby,那么最后分组的依据就是这两个序列对应行的唯一组合:

df.groupby([condition, item])['Height'].mean()
Weight   
False   a    157.910000
        b    158.412500
        c    160.521277
True    a    171.116667
        b    171.050000
        c    176.133333
Name: Height, dtype: float64

由此可以看出,之前传入列名只是一种简便的记号,事实上等价于传入的是一个或多个列,最后分组的依据来自于数据来源组合的unique值,通过drop_duplicates就能知道具体的组类别:

在这里插入图片描述

df.groupby([df['School'], df['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

上面的结果与前面df.groupby(['School', 'Gender'])['Height'].mean()一致。所以groupby()里就是传入序列(行数与df一致),根据其unique值分组。

3. Groupby对象

能够注意到,最终具体做分组操作时,所调用的方法都来自于pandas中的groupby对象,这个对象上定义了许多方法,也具有一些方便的属性。

gb = df.groupby(['School', 'Grade'])
gb
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f9d8b4c83d0>

通过ngroups属性,可以访问分为了多少组

gb.ngroups
#16

通过groups属性,可以返回从组名组名映射到组索引列表组索引列表的字典(多序列分组的组名是元组):

在这里插入图片描述

单序列分组

在这里插入图片描述

【练一练2】

上一小节介绍了可以通过drop_duplicates得到具体的组类别,现请用groups属性完成类似的功能。

【解答】
def group_df(name):
    gb=df.groupby(name)
    res=gb.groups
    df_groups=pd.DataFrame()
    for j in range(len(name)):
        list1=[]
        for i in res.keys():
            list1.append(i[j])
        df_groups[name[j]]=pd.Series(list1)
    return df_groups
name=['School','Gender','Grade']
group_df(name)
【END】

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值