DataFrame(14):对比MySQL学习“Pandas的groupby分组聚合”(超详细)

举报
yd_226342373 发表于 2021/05/21 01:51:04 2021/05/21
【摘要】 本文叙述使用的“数据集”链接下载地址如下: http://note.youdao.com/noteshare?id=5f44492149116cb6c52233786c1ca98d&sub=6C35AFC6AF9441648F245393DCAC61CB 1、MySQL和Pandas做分组聚合的对比说明 1)都是用来处理表格数据   不管是mysql,还是...

本文叙述使用的“数据集”链接下载地址如下:
http://note.youdao.com/noteshare?id=5f44492149116cb6c52233786c1ca98d&sub=6C35AFC6AF9441648F245393DCAC61CB

1、MySQL和Pandas做分组聚合的对比说明

1)都是用来处理表格数据

  不管是mysql,还是pandas,都是处理像excel那样的二维表格数据的。对于一个二维表,每一行都可以看作是一条记录,每一列都可以看作是字段。

2)分组聚合的风格不同

  学过mysql的人都知道,mysql在做数据处理和统计分析的时候,有一个很大的痛点:语法顺序和执行顺序不一致,这就导致很多初学者很容易写错sql语句。
  业界处理像excel那样的二维表格数据,通常有如下两种风格:

  • DSL风格:使用面向对象的方式来操作,pandas就是采用这种方式,通俗说就是“语法顺序和执行顺序一致”。
  • SQL风格:写sql语句来处理。
3)从代码角度,说明两者的不同
① mysql

语法顺序:

SELECT Column1, Column2, mean(Column3), sum(Column4)  
FROM SomeTable  
WHERE Condition 1  
GROUP BY Column1, Column2  
HAVING Condition2 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

逻辑执行顺序:

from...where...group...select...having...limit

  
 
  • 1
② pandas

语法顺序和逻辑执行顺序:

df[Condition1].groupby([Column1,Column2],as_index=False).agg({Column3: "mean",Column4:"sum"})

  
 
  • 1
③ 图示说明

在这里插入图片描述

  • 首先from相当于取出MySQL中的一张表,对比pandas就是得到了一个df表对象。
  • 然后就是执行where筛选,对比pandas就相当于写一个condition1过滤条件,做一个分组前的筛选筛选。
  • 接着就是执行group分组条件,对比pandas就是写一个groupby条件进行分组。
  • 再接着就是执行select条件,聚合函数就是写在select后面的,对比pandas就是执行agg()函数,在其中针对不同的列执行count、max、min、sum、mean聚合函数。
  • 最后执行的是having表示分组后的筛选,在pandas中,通过上图可以发现我们得到了一个df1对象,针对这个df1对象,我们再做一次筛选,也表示分组后的筛选。
  • 综上所述:只要你的逻辑想好了,在pandas中,由于语法顺序和逻辑执行顺序是一致的,你就按照逻辑顺序写下去,就很容易了。
4)用一个例子讲述MySQL和Pandas分组聚合
① 求不同deptno(部门)下,sal(工资)大于8000的部门、工资;

在这里插入图片描述

② mysqi中代码执行如下
select deptno,sum(sal) sums
from emp
group by deptno
having sums > 9000;

  
 
  • 1
  • 2
  • 3
  • 4

结果如下:
在这里插入图片描述

③ pandas中代码执行如下
df = pd.read_excel(r"C:\Users\黄伟\Desktop\emp.xlsx")
display(df)

df = df.groupby("deptno",as_index=False).agg({"sal":"sum"})
display(df)

df1 = df[df["sal"]>9000]
display(df1)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

结果如下:
在这里插入图片描述

2、groupby分组聚合的原理说明

1)原理图

在这里插入图片描述

2)原理说明
  • split:按照指定规则分组,由groupby实现;
  • apply:针对每个小组,使用函数进行操作,得到结果,由agg()函数实现;
  • combine:将每一组得到的结果,汇总起来,得到最终结果;
  • 注意:combine这一步是自动完成的,因此针对pandas中的分组聚合,我们只需要学习两个内容,① 学习怎么分组;② 学习如何针对每个分组中的数据,进行对应的逻辑操作;

3、groupby分组对象的相关操作

  我们可以通过groupby方法来对Series或DataFrame对象实现分组操作,该方法会返回一个分组对象。但是,如果直接查看(输出)该对象,并不能看到任何的分组信息。

1)groupby()函数语法
① 语法如下
  • groupby(by=[“字段1”,“字段2”,…],as_index=True)
② 参数说明
  • by参数传入的分组字段,当只有一个字段的时候,可以直接写by=“字段1”。当多字段联合分组的时候,就写成列表形式by=[“字段1”,“字段2”]。
  • as_index参数的使用如图所示
    在这里插入图片描述
③ 参数as_index的使用说明
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)

df.groupby("name",as_index=True).agg({"num":"sum"})
df.groupby("name",as_index=False).agg({"num":"sum"})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:
在这里插入图片描述

2)groupby分组对象的常用方法或属性。
① groups属性:返回一个字典,key表示组名,value表示这一组中的所有记录;
② size()方法:返回每个分组的记录数;
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)

df.groupby("deptno").groups
df.groupby("deptno").size()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:
在这里插入图片描述

3)使用for循环打印groupby()分组对象中每一组的具体数据
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)

groupdf = df.groupby("name")
for (x,y) in groupdf: display(x, y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:
在这里插入图片描述
4)groupby()分组参数的4种形式

  • 单字段分组:根据df中的某个字段进行分组。
  • 多字段分组:根据df中的多个字段进行联合分组。
  • 字典或Series:key指定索引,value指定分组依据,即value值相等的记录,会分为一组。
  • 自定义函数:接受索引,索引相同的记录,会分为一组。

使用如下数据演示这4种分组参数:

df = pd.DataFrame({"部门":["A", "A", "B", "B"], "小组":["g1", "g2", "g1", "g2"], "利润":[10, 20, 15, 28], "人员":["a", "b", "c", "d"], "年龄":[20, 15, 18, 30]})
display(df)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:
在这里插入图片描述

① 单字段分组:根据df中的某个字段进行分组。
g = df.groupby("部门")
display(g)

for (x,y) in g: display(x, y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述

② 多字段分组:根据df中的多个字段进行联合分组。
g = df.groupby(["部门","小组"])
display(g)

for (x,y) in g: display(x, y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述

③ 字典:key指定索引,value指定分组依据,即value值相等的记录,会分为一组。
g = df.groupby({0:1, 1:1, 2:1, 3:2})
display(g)

for (x,y) in g: display(x, y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述

④ Series:分组排序(很重要)
df = pd.DataFrame({"部门":["A", "A", "A", "B", "B", "B"], "利润":[10, 32, 20, 15, 28, 10], "销售量":[20, 15, 33, 18, 30, 22]})
display(df)

df["排名"] = df["销售量"].groupby(df["部门"]).rank()
df

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:
在这里插入图片描述

⑤ 自定义函数:将部门A、B分为一组,C单独成为一组(很特别的需求)
df = pd.DataFrame({"部门":["A", "A", "B", "B", "C", "C"], "小组":["g1", "g2", "g1", "g2", "g1", "g2"], "利润":[10, 20, 15, 28, 12, 14], "人员":["a", "b", "c", "d", "e", "f"], "年龄":[20, 15, 18, 30, 23, 34]})
df = df.set_index("部门")
display(df)

def func(x): if x=="A" or x=="B": return 0 else: return 1

g = df.groupby(func)
display(g)

for (x,y) in g: display(x, y)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

结果如下:
在这里插入图片描述

4、agg()聚合操作的相关说明

  当使用了groupby()分组的时候,得到的就是一个分组对象。当没有使用groupby()分组的时候,整张表可以看成是一个组,也相当于是一个分组对象。
  针对分组对象,我们既可以直接调用聚合函数sum()、mean()、count()、max()、min(),还可以调用分组对象的agg()方法,然后像agg()中传入指定的参数。

1)直接针对分组对象,调用聚合函数
① 针对df整张表,直接调用聚合函数
df = pd.DataFrame({"部门":["A", "A", "B", "B", "C", "C"], "小组":["g1", "g2", "g1", "g2", "g1", "g2"], "利润":[10, 20, 15, 28, 12, 14], "人员":["a", "b", "c", "d", "e", "f"], "年龄":[20, 15, 18, 30, 23, 34]})
display(df)

df["利润"].mean()
df[["年龄","利润"]].mean()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果如下:
在这里插入图片描述

② 针对df分组后的对象,直接调用聚合函数
df = pd.DataFrame({"部门":["A", "A", "B", "B", "C", "C"], "小组":["g1", "g2", "g1", "g2", "g1", "g2"], "利润":[10, 20, 15, 28, 12, 14], "人员":["a", "b", "c", "d", "e", "f"], "年龄":[20, 15, 18, 30, 23, 34]})
display(df)

df.groupby("部门")["利润"].mean()
df.groupby("部门").mean()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果如下:
在这里插入图片描述

2)直接针对分组对象,调用agg()函数(很重要)

  下面知识的讲解,涉及到“聚合函数字符串”,这是我自己起的名字,类似于"sum"、“mean”、“count”、“max”、“min”,都叫做“聚合函数字符串”。同时还需要注意一点,agg()函数中还有一个axis参数,用于指定行、列。

  • df.agg(“mean”)
  • df.agg([“mean”, “sum”, “max”])
  • df.agg({“利润”:[“mean”, “sum”] , “年龄”:[“max”, “min”]})
  • df.agg(lambda x: x.mean())
① 传入单个聚合函数字符串
df = pd.DataFrame({"部门":["A", "A", "B", "B"], "利润":[10, 20, 15, 28], "年龄":[20, 15, 18, 30]})
display(df)

df1 = df.groupby("部门").agg("mean")
display(df1)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:
在这里插入图片描述

② 传入多个聚合函数字符串
df = pd.DataFrame({"部门":["A", "A", "B", "B"], "利润":[10, 20, 15, 28], "年龄":[20, 15, 18, 30]})
display(df)

df1 = df.groupby("部门").agg(["sum","mean"])
display(df1)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:
在这里插入图片描述

③ 传入一个字典:可以针对不同的列,提供不同的聚合信息。
df = pd.DataFrame({"部门":["A", "A", "B", "B"], "利润":[10, 20, 15, 28], "年龄":[20, 15, 18, 30]})
display(df)

df1 = df.groupby("部门").agg({"利润":["sum","mean"],"年龄":["max","min"]})
display(df1)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果如下:
在这里插入图片描述

④ 传入自定义函数
df = pd.DataFrame({"部门":["A", "A", "A", "B", "B", "B"], "利润":[10, 32, 20, 15, 28, 10], "销售量":[20, 15, 33, 18, 30, 22]})
display(df)

df.groupby("部门").agg(lambda x:x.max()-x.min())

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:
在这里插入图片描述

文章来源: blog.csdn.net,作者:数据分析与统计学之美,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_41261833/article/details/104232262

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200