pandas分组
- 分组的释义
- 什么是分组?
- 怎么进行分组?
- 分组的基本步骤
- 分组的代码实战
- 1. 单个列表头类别进行分组:
- 2. 多类别嵌套分组
- 3. 根据条件进行分组
- 4. 条件 + 列表头类别分组
- 5. 函数条件 + 列表头类别分组
- 分组函数的属性
分组的释义
什么是分组?
中文:分组 = (分组作动词时:把一堆人或物按照一定的规则划分成几组人或物) = 分成各个不同的类别。
英文:分组 = grouping(动词)
分组(名词) = group: A group is a set of people, organizations, or things which are considered together because they have something in common.
计算机用语:把数据按照一定的规则进行有效地分割成小块数据,便于统计和查找。这里的小块实际上是 packet
怎么进行分组?
通过上面的词语解释,我们可以进行剥茧抽丝:
要对谁分组 --> 要对一堆人或物 --> 一堆人或物 = 数据(数据来源)
要怎样分组 --> 按照一定规则进行 --> 一定规则 = 分组依据
要做什么 = 完成分组之后,要对分好的组进行什么样的操作 = 操作及返回结果
分组的基本步骤
- 数据获取
import numpy as np
import pandas as pd
import 其他库
path =数据来源
按照数据存储的文件类型进行读取数据操作
常见的数据读取操作:(点击查看)
常见的数据获取操作:(点击查看)
- 数据观察
1. 大概浏览 .head() , .tail()
2. 基本信息和统计数据 . info() , .describe()
3. 主要的类别和业务指标的关联程度 --> 数据特征的统计函数
数据特征的统计函数相关内容:(点击查看)
- 确定分组依据
定下来分组依据之后: 用.groupby() 方法:
数据变量.groupby(分组依据)[数据类别]
- 进行分组后的操作
数据变量.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() 等方法。