当前位置: 首页 > article >正文

Pandas-数据分组

文章目录

  • 一. 分组+聚合
    • 1. 分组聚合过程
    • 2. Pandas,Numpy内置的聚合方法
    • 3. 聚合函数
      • ① 使用Numpy库的mean函数
      • ② 自定义函数
        • Ⅰ. 一个参数
        • Ⅱ. 多个参数
      • ③ agg和 aggregate
        • Ⅰ. 传入一个函数
        • Ⅱ. 同时传入多个函数
        • Ⅲ. 向agg/aggregate中传入字典
  • 二. 分组+转换
    • 1. 使用transform分组计算z分数
    • 2. transform分组填充缺失值
    • 3. 栗子-transform
  • 三.分组+过滤
  • 四. DataFrameGroupBy对象
    • 1. DataFrameGroupBy对象
    • 2. 通过groups属性查看计算过的分组
    • 3. 在DataFrameGroupBy对象基础上,直接就可以进行aggregate,transform计算了
    • 4. 通过get_group选择分组
    • 5. 遍历分组
    • 6. 多个分组

一. 分组+聚合

在SQL中我们经常使用 GROUP BY 将某个字段,按不同的取值进行分组, 在pandas中也有groupby函数
分组之后,每组都会有至少1条数据, 将这些数据进一步处理返回单个值的过程就是聚合,比如分组之后计算算术平均值, 或者分组之后计算频数,都属于聚合

加载数据

import pandas as pd

df = pd.read_csv('data/gapminder.tsv',sep='\t')
df

在这里插入图片描述

1. 分组聚合过程

groupby语句创建若干组,对year字段分组, 会将数据中不同年份作为分组结果

df.groupby('year').lifeExp.mean()

在这里插入图片描述
查询年份

df.year.nunique()

在这里插入图片描述

years = df.year.unique()

在这里插入图片描述
上面groupby 之后取平均的结果,也可以手动计算

y1952 = df.loc[df.year == 1952, :]
y1952

在这里插入图片描述

y1952.lifeExp.mean()
49.057619718309866

groupby 语句会针对每个不同年份重复上述过程,并把所有结果放入一个DataFrame中返回
mean函数不是唯一的聚合函数, Pandas内置了许多方法, 都可以与groupby语句搭配使用

2. Pandas,Numpy内置的聚合方法

可以与groupby一起使用的方法和函数
在这里插入图片描述
上图都是可以与groupby一起使用的方法和函数
前面例子中分组之后取平均也可以使用describe函数同时计算多个统计量

df.groupby('year').lifeExp.describe()

在这里插入图片描述

3. 聚合函数

① 使用Numpy库的mean函数

import numpy as np
df.groupby('continent').lifeExp.agg('mean')
df.groupby('continent').lifeExp.agg(np.mean)
df.groupby('continent').lifeExp.aggregate('mean')
df.groupby('continent').lifeExp.aggregate(np.mean)

在这里插入图片描述
agg和 aggregate效果一样

② 自定义函数

Ⅰ. 一个参数

如果想在聚合的时候,使用非Pandas或其他库提供的计算,可以自定义函数然后在aggregate中调用它

def my_mean(values):
    #计算平均值
    #获取数据条目数
    n = len(values)
    # n1 = values.size
    # n2 = values.count()
    # print(n, n1, n2)
    sum = 0
    for value in values:
        sum += value
    return sum / n

df.groupby('year').lifeExp.agg(my_mean)

调用自定义函数 df.groupby(‘year’).lifeExp.agg(my_mean)
自定义函数中只有一个参数values,但传入该函数中的数据是一组值,需要对values进行迭代才能取出每一个值

Ⅱ. 多个参数

自定义函数可以有多个参数,第一个参数接受来自DataFrame分组这之后的值, 其余参数可自定义

def my_mean_diff(values,diff_value):
    #计算平均值和diff_value的差值

    #获取数据条目数
    n = len(values)

    sum = 0
    for value in values:
        sum += value
    mean = sum / n
    return mean - diff_value

df.groupby('year').lifeExp.agg(my_mean_diff,diff_value=50)

在这里插入图片描述

③ agg和 aggregate

Ⅰ. 传入一个函数
df.groupby('continent').lifeExp.agg('mean')
df.groupby('continent').lifeExp.aggregate('mean')

在这里插入图片描述

df.groupby('continent').agg({'lifeExp': 'mean'})

在这里插入图片描述

Ⅱ. 同时传入多个函数
df.groupby('year').lifeExp.agg(['mean','count'])
df.groupby('year').lifeExp.aggregate(['mean',np.count_nonzero])

在这里插入图片描述

不带中括号,只保留第一组

df.groupby('year').lifeExp.agg('mean','count')
df.groupby('year').lifeExp.aggregate('mean',np.count_nonzero)

在这里插入图片描述

只保留最后一组

df.groupby('year').agg({'lifeExp': 'mean', 'lifeExp': 'count'})

在这里插入图片描述

Ⅲ. 向agg/aggregate中传入字典
df.groupby('year').agg({'lifeExp':'mean','pop':'median','gdpPercap':'max'})
df.groupby('year')[['lifeExp','pop','gdpPercap']].agg('mean','median','max')

在这里插入图片描述

df.groupby('year')[['lifeExp','pop','gdpPercap']].agg({'mean','median','max'})
df.groupby('year')[['lifeExp','pop','gdpPercap']].agg(['mean','median','max'])

在这里插入图片描述

二. 分组+转换

transform 需要把DataFrame中的值传递给一个函数, 而后由该函数"转换"数据。
aggregate(聚合) 返回单个聚合值,但transform 不会减少数据量

1. 使用transform分组计算z分数

计算z-score x - 平均值/标准差

def my_zscore(x):
    return (x - x.mean()) / x.std()

df.groupby('year').lifeExp.transform(my_zscore)

在这里插入图片描述
查看数据集条目数, 跟之前transform处理之后的条目数一样

df.shape
(1704, 6)

2. transform分组填充缺失值

前介绍了填充缺失值的各种方法,对于某些数据集,可以使用列的平均值来填充缺失值。
某些情况下,可以考虑将列进行分组,分组之后取平均再填充缺失值

加载数据

tips_10 = pd.read_csv('data/tips.csv').sample(10, random_state=42)
tips_10

在这里插入图片描述

构建缺失值

tips_10.loc[np.random.permutation(tips_10.index)[:4],'total_bill'] = np.nan
tips_10

在这里插入图片描述

查看缺失值情况
count_sex = tips_10.groupby(‘sex’).count()
count_sex
在这里插入图片描述
定义函数填充缺失值

def fill_na_mean(x):
    avg = x.mean()
    return x.fillna(avg)

total_bill_group_mean = tips_10.groupby('sex').total_bill.transform(fill_na_mean)
total_bill_group_mean

在这里插入图片描述

将计算的结果赋值新列

tips_10['fill_total_bill'] = total_bill_group_mean
tips_10

在这里插入图片描述

对比total_bill 和 fill_total_bill 发现 Male 和 Female 的填充值不同

3. 栗子-transform

weight_loss数据集,找到减肥比赛赢家

  • 加载数据

    weight_loss = pd.read_csv('data/weight_loss.csv')
    weight_loss.head()
    

    在这里插入图片描述
    Bob,Amy两个人的减肥记录,从1月到4月

  • 只查看1月份数据 query 类似SQL的where条件

    weight_loss.query('Month == "Jan"')
    weight_loss[weight_loss['Month'] == 'Jan']
    

    在这里插入图片描述

  • 定义函数计算每周减肥比例 并测试

    def find_perc_loss(s):
        return (s-s.iloc[0])/s.iloc[0]
    #查找Bob 1月份的数据
    bob_jan = weight_loss.query("Name=='Bob' and Month=='Jan'")
    # bob_jan = weight_loss[weight_loss['Name'] == 'Bob' and weight_loss['Month'] == 'Jan']#报错
    Bob_jan
    

    在这里插入图片描述

    #测试计算减肥比例的方法
    find_perc_loss(bob_jan['Weight'])
    

    在这里插入图片描述

  • 计算每周减肥比例

    pcnt_loss = weight_loss.groupby(['Name','Month'])['Weight'].transform(find_perc_loss)
    pcnt_loss.head(8)
    

    在这里插入图片描述

    weight_loss['Perc Weight Loss'] = pcnt_loss.round(3)
    weight_loss
    

    查找每个月最后一周的数据 用来比较减肥效果

    week4 = weight_loss.query('Week == "Week 4"')
    week4
    

    在这里插入图片描述

  • 在第四周数据基础上,找到 Bob 和 Amy的减肥数据

    week4_Amy = week4.query('Name == "Amy"')[['Month','Perc Weight Loss']]
    week4_Amy
    

    在这里插入图片描述

    week4_Bob = week4.query('Name == "Bob"')[['Month','Perc Weight Loss']]
    week4_Bob
    

    在这里插入图片描述

  • 比较Bob 和 Amy的减肥效果, Amy的减肥效果更明显

    week4_Bob.set_index('Month')-week4_Amy.set_index('Month')
    

    在这里插入图片描述

三.分组+过滤

使用groupby方法还可以过滤数据
调用filter 方法,传入一个返回布尔值的函数,返回False的数据会被过滤掉

使用小费数据

tips = pd.read_csv('data/tips.csv')
tips.head()

在这里插入图片描述

查看用餐人数

tips['size'].value_counts()

在这里插入图片描述

人数为1、5和6人的数据比较少,考虑将这部分数据过滤掉

tips_filtered= tips.groupby('size').filter(lambda x:x['size'].count()>30)
tips_filtered

在这里插入图片描述

查看结果

tips_filtered['size'].value_counts()

在这里插入图片描述

四. DataFrameGroupBy对象

1. DataFrameGroupBy对象

准备数据

tips_10 = pd.read_csv('data/tips.csv').sample(10,random_state = 42)
tips_10

在这里插入图片描述

调用groupby 创建分组对象

grouped = tips_10.groupby('sex')

查看grouped

grouped

grouped是一个DataFrameGroupBy对象
在这里插入图片描述

2. 通过groups属性查看计算过的分组

grouped.groups

在这里插入图片描述
上面返回的结果是DataFrame的索引,实际上就是原始数据的行数

3. 在DataFrameGroupBy对象基础上,直接就可以进行aggregate,transform计算了

grouped.mean()

在这里插入图片描述
上面结果直接计算了按sex分组后,所有列的平均值,但只返回了数值列的结果,非数值列不会计算平均值

4. 通过get_group选择分组

female = grouped.get_group('Female')
female

在这里插入图片描述

5. 遍历分组

通过groupby对象,可以遍历所有分组
相比于在groupby之后使用aggregate、transform和filter,有时候使用for循环解决问题更简单

for sex_group in grouped:
    print(sex_group)

在这里插入图片描述

DataFrameGroupBy对象直接传入索引,会报错 grouped[0]

for sex_group in grouped:
    #遍历grouped对象,查看sex_group数据类型
    print(type(sex_group))
    #查看元素个数
    print(len(sex_group))
    #查看第一个元素
    print(sex_group[0])
    break

在这里插入图片描述

6. 多个分组

前面使用的groupby语句只包含一个变量,可以在groupby中添加多个变量

使用groupby按性别和用餐时间分别计算小费数据的平均值

group_avg = tips_10.groupby(['sex','time']).mean()

在这里插入图片描述

分别查看分组之后结果的列名和行索引

group_avg.columns

在这里插入图片描述

group_avg.index

在这里插入图片描述
多个分组之后返回的是MultiIndex

在结果上调用reset_index方法得到一个普通的DataFrame

group_avg.reset_index()

也可以在分组的时候通过as_index = False参数(默认是True),效果与调用reset_index()一样

tips_10.groupby(['sex','time'],as_index = False).mean()

http://www.kler.cn/a/463916.html

相关文章:

  • SAP SD销售模块常见BAPI函数
  • [cg] android studio 无法调试cpp问题
  • 第2章:SQL基础
  • ‘元素.style.样式名‘获取不到样式,应该使用Window.getComputedStyle()获取正真的样式
  • 5大常见高并发限流算法选型浅析
  • Rockect基于Dledger的Broker主从同步原理
  • Seata AT 模式两阶段过程原理解析【seata AT模式如何做到对业务的无侵入】
  • 前端:轮播图常见的几种实现方式
  • CSS 实现无限滚动的列表
  • Unity+Hybridclr发布WebGL记录
  • 自动化运维脚本的最佳设计模式与开发指南
  • css的长度单位有那些?
  • 工业软件发展添动力 深圳龙华与华为云再聚“首”
  • Redis--缓存穿透、击穿、雪崩以及预热问题(面试高频问题!)
  • pytorch将数据与模型都放到GPU上训练
  • OpenGL ES 04 图片数据是怎么写入到对应纹理单元的
  • chatwoot 开源客服系统搭建
  • 安卓入门五 BroadcastReceiver
  • ARM/Linux嵌入式面经(六二):诺瓦星云
  • 年会投票小游戏
  • MySQL标准合规
  • 【ubuntu】安装OpenSSH服务器
  • 攻防世界web第六题upload1
  • 如何使用交叉编译器调试C语言程序在安卓设备中运行
  • 计算机网络原理(谢希仁第八版)第3章课后习题答案
  • vscode ssh远程连接已配置好仍然不能自动登录问题解决