pandas分组

分组的释义

什么是分组?

中文:分组 = (分组作动词时:把一堆人或物按照一定的规则划分成几组人或物) = 分成各个不同的类别。

英文:分组 = grouping(动词)
分组(名词) = group: A group is a set of people, organizations, or things which are considered together because they have something in common.

计算机用语:把数据按照一定的规则进行有效地分割成小块数据,便于统计和查找。这里的小块实际上是 packet

怎么进行分组?

通过上面的词语解释,我们可以进行剥茧抽丝:

要对谁分组 --> 要对一堆人或物  --> 一堆人或物 = 数据(数据来源)

要怎样分组 --> 按照一定规则进行  --> 一定规则 = 分组依据

要做什么 = 完成分组之后,要对分好的组进行什么样的操作 = 操作及返回结果

分组的基本步骤

  1. 数据获取

     import numpy as np
     import pandas as pd
     import 其他库
     
     path =数据来源
     按照数据存储的文件类型进行读取数据操作
    

    常见的数据读取操作:(点击查看
    常见的数据获取操作:(点击查看

  2. 数据观察

     1. 大概浏览   .head() , .tail()
     2. 基本信息和统计数据  . info()  ,   .describe()
     3. 主要的类别和业务指标的关联程度  --> 数据特征的统计函数
    

    数据特征的统计函数相关内容:(点击查看

  3. 确定分组依据

     定下来分组依据之后: 用.groupby() 方法:
     数据变量.groupby(分组依据)[数据类别]
    
  4. 进行分组后的操作

     数据变量.groupby(分组依据)[待操作数据的类别].具体操作
    

    理解: 把数据按照分组依据选出来,在其中对待操作的数据类别,进行具体操作。

分组的代码实战

先上代码,看一下写法的不同输出结果:

1. 单个列表头类别进行分组:

import pandas as pd

# pandas显示所有数据
pd.set_option("display.max_columns", None)
pd.set_option("display.max_rows", None)
pd.set_option("max_colwidth", 100)
# 数据读取
path = r"F:\Python_Tensorflow_codes\001竞赛代码\joyful-pandas-master\data\learn_pandas.csv"
df = pd.read_csv(path, encoding="gbk")

print(df.groupby("Gender"))
print("-"*15)
print(df.groupby("Gender").head())
print("-"*15)
print(df.groupby("Gender")["Height"])
print("-"*15)
print(df.groupby("Gender")["Height"].head())
print("-"*15)
print(df.groupby("Gender")["Height"].median())

运行结果:

<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002CEF0F07A60>
---------------
                           School      Grade            Name  Gender  Height  \
0   Shanghai Jiao Tong University   Freshman    Gaopeng Yang  Female   158.9   
1               Peking University   Freshman  Changqiang You    Male   166.5   
2   Shanghai Jiao Tong University     Senior         Mei Sun    Male   188.9   
3                Fudan University  Sophomore    Xiaojuan Sun  Female     NaN   
4                Fudan University  Sophomore     Gaojuan You    Male   174.0   
5             Tsinghua University   Freshman     Xiaoli Qian  Female   158.0   
6   Shanghai Jiao Tong University   Freshman       Qiang Chu  Female   162.5   
7             Tsinghua University     Junior   Gaoqiang Qian  Female   161.9   
10  Shanghai Jiao Tong University   Freshman   Xiaopeng Zhou    Male   174.1   
16            Tsinghua University     Junior   Xiaoqiang Qin    Male   170.1   

    Weight Transfer  Test_Number   Test_Date Time_Record  
0     46.0        N            1   2019/10/5     0:04:34  
1     70.0        N            1    2019/9/4     0:04:20  
2     89.0        N            2   2019/9/12     0:05:22  
3     41.0        N            2    2020/1/3     0:04:08  
4     74.0        N            2   2019/11/6     0:05:22  
5     51.0        N            1  2019/10/31     0:03:47  
6     52.0        N            1  2019/12/12     0:03:53  
7     50.0        N            1    2019/9/3     0:03:45  
10    74.0        N            1   2019/9/29     0:05:16  
16    68.0        N            1   2019/9/11     0:04:51  
---------------
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000002CEEEA491C0>
---------------
0     158.9
1     166.5
2     188.9
3       NaN
4     174.0
5     158.0
6     162.5
7     161.9
10    174.1
16    170.1
Name: Height, dtype: float64
---------------
Gender
Female    159.6
Male      173.4
Name: Height, dtype: float64

有疑问?

问题: .head()指令是:输出数据的默认的前五行数据信息的, 这里为什么是前16行。

回答:因为在进行分组之后,df.groupby(“Gender”)分成了两个组,这两个元素在数据中属于同一个组,head()要显示前五个信息,则便会以两个组的形式打印5行信息。
在这里插入图片描述

2. 多类别嵌套分组

多个列表头类别构成同一个列表,然后传入 .groupby() 中

数据变量名.gruopby( [列名1, 列名2, 列名3, ……] )[对哪个指标].进行什么样的操作
使不同的类别相互组合,并形成嵌套关系

代码实战:

import numpy as np
import pandas as pd

# pandas显示所有数据
pd.set_option("display.max_columns", None)
pd.set_option("display.max_rows", None)
pd.set_option("max_colwidth", 100)
# 数据读取
path = r"F:\Python_Tensorflow_codes\001竞赛代码\joyful-pandas-master\data\learn_pandas.csv"
df = pd.read_csv(path, encoding="gbk")

res = df.groupby(["School", "Grade", "Gender"])["Height"].mean()
print(res)

运行结果:

School                         Grade      Gender
Fudan University               Freshman   Female    158.757143
                                          Male      176.300000
                               Junior     Female    158.385714
                                          Male      172.100000
                               Senior     Female    157.555556
                                          Male      177.150000
                               Sophomore  Female    163.400000
                                          Male      172.966667
Peking University              Freshman   Female    158.428571
                                          Male      174.180000
                               Junior     Female    161.566667
                                          Male      166.800000
                               Senior     Female    158.300000
                                          Male      169.933333
                               Sophomore  Female    155.100000
                                          Male      172.800000
Shanghai Jiao Tong University  Freshman   Female    160.350000
                                          Male      176.350000
                               Junior     Female    159.193333
                                          Male      174.350000
                               Senior     Female    158.407692
                                          Male      176.737500
                               Sophomore  Female    158.725000
                                          Male      183.400000
Tsinghua University            Freshman   Female    160.360000
                               Junior     Female    160.441667
                                          Male      170.800000
                               Senior     Female    159.480000
                                          Male      176.775000
                               Sophomore  Female    157.925000
                                          Male      169.040000
Name: Height, dtype: float64

下面将以思维导图的形式展现运行过程:
在这里插入图片描述
代码实战2:

print(df.groupby(["School", "Gender"])["Height"].mean())
print("-"*44)
print(df.groupby([df["School"], df["Gender"]])["Height"].mean())
print("-"*44)

运行结果:

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
--------------------------------------------
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() 是
	利用多个类别组成列表,进行分组操作。是将多个类别组合起来(嵌套起来)
	
df.groupby([df["School"], df["Gender"]])["Height"].mean() 是先将类别
	对应的值提取,然后组成列表,然后在进行选择
具体请看下面代码:
print(df[["School", "Gender"]].head())
print("-"*44)
print([df["School"].head(), df["Gender"].head()])

运行结果:

                          School  Gender
0  Shanghai Jiao Tong University  Female
1              Peking University    Male
2  Shanghai Jiao Tong University    Male
3               Fudan University  Female
4               Fudan University    Male
--------------------------------------------
[0    Shanghai Jiao Tong University
1                Peking University
2    Shanghai Jiao Tong University
3                 Fudan University
4                 Fudan University
Name: School, dtype: object, 0    Female
1      Male
2      Male
3    Female
4      Male
Name: Gender, dtype: object]

可以看出:

 df[["School", "Gender"]]  不等于  [ df["School"], df["Gender"] ]
 其中:
 df[ ["School", "Gender"] ] 这个是纵向选取列类别的值,为 DataFrame类型
 
  [ df["School"], df["Gender"] ] 是各自选取, 
  df["School"]和df["Gender"] , 并且两者都是Series结构,(有下标,有值)
  然后在用 [ ] 组成  列表类型。

注意:

df.groupby(df[["School", "Gender"]])["Height"].mean() 是错误的,
因为df[["School", "Gender"]] 是df的数据本身,而不是列表头类别。所以不能通过这种形式进行分组。

3. 根据条件进行分组

	确定筛选条件并进行设置,condition = ……

	将条件传入分类依据中, 数据变量.groupby(分组依据)[数据类别]

	确定分组后的相关操作, 数据变量.groupby(分组依据)[待操作数据的类别].具体操作

代码实战1:

# 按条件选择分组
condition = df.Weight > df.Weight.mean()
print(df.groupby(condition)["Height"].mean())

运行结果:

Weight
False    159.034646
True     172.705357
Name: Height, dtype: float64

4. 条件 + 列表头类别分组

condition = df.Weight > df.Weight.mean()
print(df.groupby([condition, "Gender"])["Height"].mean())
print("-"*44)
print(df.groupby([condition, df["Gender"]])["Height"].mean())
print("-"*44)
print(df.groupby([condition, "Gender", "School"])["Height"].mean())

运行结果:

Weight  Gender
False   Female    158.674797
        Male      170.100000
True    Female    166.333333
        Male      173.925532
Name: Height, dtype: float64
--------------------------------------------
Weight  Gender
False   Female    158.674797
        Male      170.100000
True    Female    166.333333
        Male      173.925532
Name: Height, dtype: float64
--------------------------------------------
Weight  Gender  School                       
False   Female  Fudan University                 157.660870
                Peking University                157.800000
                Shanghai Jiao Tong University    158.765789
                Tsinghua University              159.523256
        Male    Peking University                172.800000
                Shanghai Jiao Tong University    177.300000
                Tsinghua University              165.150000
True    Female  Fudan University                 167.333333
                Peking University                166.900000
                Shanghai Jiao Tong University    165.900000
                Tsinghua University              164.700000
        Male    Fudan University                 174.212500
                Peking University                171.944444
                Shanghai Jiao Tong University    176.721429
                Tsinghua University              172.450000
Name: Height, dtype: float64

上面讲的例子都是已存在的类别,如果要生成原始数据中不存在的类别,则可以使用groupby()方法。

item = np.random.choice(list('abc'), df.shape[0])
print(df.groupby([condition, item])['Height'].mean())

运行结果:

Weight   
False   a    159.304348
        b    158.942105
        c    158.827907
True    a    171.525000
        b    172.835294
        c    173.430435
Name: Height, dtype: float64

解释:

item = np.random.choice(list('abc'), df.shape[0]) 
产生了df.shape[0]个数据,随机产生的数据为 list("abc")的输出值:“a”, “b”, “c”
df.shape[0] = df 的行元素个数

5. 函数条件 + 列表头类别分组

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

问题分析:

1. 确定目标 = 我们要统计的是身高的均值,计算身高均值:df[ "Height" ].mean()
2. 直接写肯定不行,因为我们还没有对体重进行分组操作
3. 要把体重分成 3 组,high、 normal、 low ,我们知道,Weight仅仅是一对数据,没有进行名确的划分,所以要写个函数,对各个Weight进行分类,并将函数应用于该数据是上。
4. 通过 自定义的函数条件 进行分组操作(  .groupby( condition )[“Height”].mean()  )

代码实战:

Weight_4q_1 = df["Weight"].quantile(q=0.25)
Weight_4q_2 = df["Weight"].quantile(q=0.75)

def condition(x):
    if x > Weight_4q_1:
        return "high"
    elif x < Weight_4q_2:
        return "low"
    elif not(x > Weight_4q_1 or x < Weight_4q_2):
        return "normal"
res = df["Weight"].apply(condition)
print(df.groupby(res)["Height"].mean())

运行结果:

Weight
high      166.448819
low       154.119149
normal    165.144444
Name: Height, dtype: float64

分组函数的属性

先定义一下:
df 代表 pandas.DataFrame()类型的数据
gb = df.groupby( 分组依据 )

名称作用
gb.ngroups分为了多少组
gb.groups从 组名映射到 组索引列表的字典
gb.size()统计每个组的元素个数
gb.get_group((元素1, 元素2,……))可以直接获取所在组对应的行,此时必须知道组的具体名字

还有一些是分组的相关函数操作。比如:mean(), median() ,quantile() 等方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值