查看原文
其他

对比SQL,学习Pandas操作:groupby机制

尤而小屋 尤而小屋 2022-06-19

公众号:尤而小屋
作者:Peter
编辑:Peter

大家,我是Peter~~  祝大家国庆快乐🌹

在SQL或者MySQL的数据库查询操作中我们经常会使用group by关键词来表示根据某个字段分组,然后再进行后续的聚合统计操作。

在Pandas我们同样可以实现类似的功能,使用的关键字是:groupby(连在一起的)。以前写过一篇Pandas中的groupby机制详解的文章,请参考:

图解Pandas的groupby机制

聚合函数-aggregation function

不管是SQL数据库还是Pandas中,分组之后的后续操作绝大部分情况下都是进行聚合统计,下面列出常用的聚合函数:

  • 求和:sum
  • 最大值:max
  • 最小值:min
  • 均值:avg
  • 统计个数:count

SQL多表查询

现在我们有两张表:Student和Score表,二者通过s_id进行join关联

通过下面的SQL语句,我们查询出相关的4个字段:

  • 姓名
  • 性别
  • 课程编号
  • 成绩
select 
 s1.s_name  -- 姓名
 ,s1.s_sex  -- 性别
 ,s2.c_id   -- 课程编号
 ,s2.s_score  -- 成绩分数
from Student s1
join Score s2 on s1.s_id = s2.s_id;

我们将上面的结果作为临时表t,然后再进行后续的查询操作。

pymysql获取数据

为了能够使用Pandas进行数据分析,我们先连接到本地的数据库,读取到相关的数据,并且生成相应的DataFrame:

1、连接数据库

import pandas as pd
import numpy as np
import pymysql  # 连接数据库

con1 = pymysql.connect(
    host="127.0.0.1",  # 数据库ip
    port=3306,  # 端口号
    user="root",  # 用户名
    password="password",   # 密码
    charset="utf8",  # 字符编码
    db="test"  # 数据库名称
)

cur1 = con1.cursor()  # 建立游标

# 待执行的SQL语句
sql1 = """   
select 
 s1.s_name  -- 姓名
 ,s1.s_sex  -- 性别
 ,s2.c_id   -- 课程编号
 ,s2.s_score  -- 成绩分数
from Student s1
join Score s2 on s1.s_id = s2.s_id;
"""


# 在游标中执行SQL语句
cur1.execute(sql1)

刚好是18条数据,就是我们上面临时表t的结果,也是18条

2、生成数据

data1 = []
for i in cur1.fetchall():
    data1.append(i)
    
df = pd.DataFrame(data1,columns=["姓名","性别","课程id","分数"])
df
image-20210930221746184

在后续的pandas中操作中就是对这个df数据进行操作。

单个聚合函数

1、求和sum:我们想知道每个学生的总成绩是多少

SQL实现:

select
 t.s_name
 ,sum(t.s_score)
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_name;

Pandas实现:

Pandas还有另一种写法:

2、求每个同学的平均成绩avg

SQL实现:

select
 t.s_name
 ,avg(t.s_score)   -- 改成均值函数
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_name;

Pandas实现的两种不同写法:

3、求每个同学的分数最大值(最小值)的那门学科

SQL实现:

select
 t.s_name
 ,max(t.s_score)   -- 改成最大值函数
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_name;

Pandas实现过程:

4、统计个数:求每个同学参加了多少门学科的考试

SQL实现:

select
 t.s_name
 ,count(t.c_id)   -- 改成count函数,同时字段是课程c_id
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_name;

Pandas实现过程:

多个聚合函数

在查询数据的时候,我们是可以同时使用多个聚合函数的,比如:我们想查看不同性别同学的:总成绩、平均成绩、人数、成绩最大值

SQL实现过程:

select
 t.s_sex
 ,sum(t.s_score)  -- 总成绩
 ,avg(t.s_score)  -- 平均成绩
 ,count(t.s_name)  -- 统计不同性别人数
 ,max(t.s_score)  -- 成绩最大值
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_sex;   -- 根据性别分组统计

Pandas实现过程:

修改字段别名

上面的数据结果中不管是SQL还是Pandas的结果,都是使用默认的字段名称,我们可以进行相应修改,使得名字更具有意义:

单个聚合函数

还是每个同学的总成绩为例

SQL实现:通过as来取别名,as可省略

select
 t.s_name  as "姓名"   -- as可省略
 ,sum(t.s_score) as  "总成绩"  -- as可省略
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_name;

Pandas实现过程:

方式1:pandas中取别名是通过rename函数来实现的

方式2:直接修改columns属性

多个聚合函数

1、SQL实现还是通过as取别名:

select
 t.s_sex  as "性别"
 ,sum(t.s_score)  as "总成绩"  -- as可省略
 ,avg(t.s_score)  as "平均成绩"
 ,max(t.s_score)  as "最高成绩"
 ,count(t.s_name)  as "总人数"
from(
  select 
    s1.s_name  -- 姓名
    ,s1.s_sex  -- 性别
    ,s2.c_id   -- 课程编号
    ,s2.s_score  -- 成绩分数
 from Student s1
 join Score s2 on s1.s_id = s2.s_id
)t
group by t.s_sex;   -- 根据性别分组统计

2、Pandas实现

df2 = df.groupby("性别").agg(
    总成绩 = pd.NamedAgg(column="分数", aggfunc="sum"),
    平均成绩 = pd.NamedAgg(column="分数", aggfunc="mean"),
    最高成绩 = pd.NamedAgg(column="分数", aggfunc="max"),
    总人数 = pd.NamedAgg(column="课程id", aggfunc="count")
)
df2

经典图

最后奉上一张经典的图形。在这张图形中记录了我们如何:

  • 选择分组字段month
  • 相同的字段(duration)进行多个聚合操作:max、min、sum
  • 对结果取别名(重新命名):max_duration、min_duration、total_duration


推荐阅读


图解Pandas的宝藏函数:assign

电商用户复购数据实战:图解Pandas的移动函数shift

14种方式,34个案例:对比SQL,学习Pandas操作

开启Pandas进阶:图解Pandas透视表、交叉表

图解Pandas的groupby机制

尤而小屋,一个温馨的小屋。小屋主人,一手代码谋求生存,一手掌勺享受生活,欢迎你的光临

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存