PY-pandas | 分组聚合

#%%
# CY3761 | 2022-01-13 10:08
#%%
# 此为 jupyter 模版, 执行 build 后记住先执行-全部运行
# 使用 DataSpell 进行编写文档
# 变量名、函数名小写分段处理
#%%
# 导入项
import numpy as np
import pandas as pd

np.array((np, pd))
#%%
class JsonObject:
    def __init__(self, items):
        self.items = items

    def __getattribute__(self, name: str):  # 注意这个方法有个坑里面不能写入 self.* 否则会出现 循环调用
        return object.__getattribute__(self, 'items').get(name)


def print_data(o):
    o_items = dict(shape=None,size=None, index=None,columns=None, dtype=None,dtypes=None,)

    print('type\t: %s' % type(o))

    for (k,v) in o_items.items():
        try:
            o_items[k] = eval(f'o.{k}')
        except (Exception, BaseException):
            pass

        if k == 'dtypes':
            o_items[k] = {k:str(v) for k,v in dict(o_items[k]).items() }

        print('%s\t: %s' % (k, o_items[k]))

    print()
    display(o)

def get_new_file_path(file_path, string, file_ext=None):
    file_sep = '.'
    file_path_split = file_path.split(file_sep)
    file_path_split_pop = file_path_split.pop()  # 获取最后一个
    file_ext = file_path_split_pop if not file_ext else file_ext

    return file_sep.join(file_path_split) + '-' + string + file_sep + file_ext

r_rang = 26
r_chr = {k: [chr(_) for _ in range(size, size+r_rang)] for k,size in dict(b=65, s=97).items()}  # 大写字母索引 小写字母索引
r_chr = pd.DataFrame(r_chr, index=range(1, r_rang+1))  # 字母表 b: 大写 s: 小写 1 开始

def get_chr_items(k, f):
    k = k.lower()
    f = f.upper() if k == 'b' else f.lower()

    return tuple(r_chr[k][:list(r_chr[k]).index(f) + 1])

display(r_chr)

r_df = pd.DataFrame(np.random.randint(0, 100, (10, 10)), tuple(r_chr.b[:10]), tuple(r_chr.s[:10]))

# print_data(r_df)
#%% md
# 分组聚合
#%% md
## 分组
#%%
df_01 = pd.DataFrame(
    dict(
        sex=np.random.randint(0, 2, 300),  # 性别: 0-男 1-女
        cls=np.random.randint(1, 9, 300),  # 班级: 1-8 8个班

        P=np.random.randint(0, 151, 300),  # P科成绩
        K=np.random.randint(0, 151, 300),  # K科成绩
        J=np.random.randint(0, 151, 300),  # J科成绩
        T=np.random.randint(0, 151, 300),  # T科成绩
        C=np.random.randint(0, 151, 300),  # C科成绩
    )
)

# 重新设置性别列
df_01.sex = df_01.sex.map({0: '男', 1: '女'})

df_01.head()
#%%
# 分组->可迭代对象
g_01 = df_01.groupby(by='sex')  # 按性别 单分组 | [['P','J']]

len(list(g_01)) # g_01 可迭代对象 <pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000240D6033070> | 单分组是 对应列的值的条数(去重)
#%%
for a, b in g_01:
    print(a)
    display(b.head())  # 拆分成2组表格数据
#%%
# 多分组
g_02 = df_01.groupby(by=['cls', 'sex']) # 按班级、性别
print(len(list(g_02)))  # 多分组 是对应分组列条数(去重)乘积 2*8=16
for a, b in g_02:
    print(a)
    # display(b.head(1))  # 拆分成2组表格数据
#%%
# 对一列值进行分组
g_03 = df_01.P.groupby(df_01.cls)  # 通过班进行分组 单分组
print('长度', len(list(g_03)))
for a, b in g_03:
    print(a, '\b班P学科成绩', np.array(b.head())) #
#%%
g_04 = df_01.K.groupby([df_01.cls, df_01.sex])
print('长度', len(list(g_04)))
for a, b in g_04:
    print('%s班%s生K学科成绩' % (a[0], a[1]), np.array(b.head())) #
#%%
## 按数据类型进行分组
g_05 = df_01.groupby(df_01.dtypes, axis=1)
print('长度', len(list(g_05)))
for a, b in g_05:
    print('组名(数据类型)', a, b.shape, b.size)
    display(b.head())
#%%
# 按字典进行分组 | 设定键(列名)=值(分组名) | 这类似数据表中筛选字段..
g_06 = df_01.groupby(dict(
    sex='category', cls='category',
    P='IT', K='IT', T='IT', J='IT', C='IT'
), axis=1)

print('长度', len(list(g_06)))
for a, b in g_06:
    print('组名', a, b.shape, b.size)
    display(b.head())
#%% md
## 分组聚合
#%%
# 分组直接调用函数进行聚合
df_01.groupby('sex').mean().round(2)  # 按性别分组 然后求平均分
#%%
df_01.groupby('sex').count()  # 按性别分组 然后求条数
#%%
df_01.groupby('sex').sum() # 按性别分组 然后求总数
#%%
# 按照班级和性别进行分组,Python、Keras的最大值聚合
df_01.groupby(['cls', 'sex'])[['P','K']].max()
#%%
df_01.groupby(['cls', 'sex'])[['P','K']].max().T  # 数据垂直了
#%%
# 按照班级和性别进行分组,计数聚合。统计每个班,男女人数
df_01.groupby(['cls','sex']).size() # 不是用 count sum会把其他科目的也进行计算
#%%
# 基本描述性统计聚合
df_01.groupby(['cls', 'sex']).describe()
#%% md
## 分组聚合apply、transform
#%%
g_07 = df_01.groupby(['cls', 'sex'])
for a,b in g_07:  # 按班别、性别分组 8*2=16
    print(a, b.shape) # 班别 性别 数据条数 数据列数
    # display(b.head(1))
#%%
g_07[['P', 'K']].apply(np.mean).round(2)  # 使用 apply进行分组聚合 | 平均值
#%%
df_01[['sex', 'cls', 'P', 'K']].head()
#%%
# transform 需要查元数据 数据第一行 0对应元数据第一行 (女,3班) => 查看 女生3班平均分是否是 P: 64.18 K: 88.29 | 3,女,64.18,88.29 .. 尼玛
df_02 = g_07[['P', 'K']].transform(np.mean).round(2)  # 使用 transform进行分组聚合 | 啥数据? 一组数据 300 个学生的 | 这也是返回各班各科的平均分 只是对应着每个学生 学生 0是3班女的.. 1是1班男的
print(df_02.shape)
df_02.head()  # 0,64.18,88.29 | 1,80.91,78.50
#%%
g_07[['P','J']].apply(lambda _: np.mean(_)).round(2)  # 调用自定义函数也可以 这里返回的也是分组平均值
#%%
func_01 = lambda _: (_ - _.min() / (_.max() - _.min()))
g_07[['P','J']].apply(func_01).round(2)  # 调用自定义函数 有时候返回的 返回结果与transform一样
#%%
g_07[['P','J']].transform(func_01).round(2)  # 最大值最小值归一化?
#%% md
## 分组聚合agg
#%%
g_07[['T', 'K']].agg([np.min, np.max, pd.Series.count])  # 分组后使用多种统计方式
#%%
# 分组后不同属性应用多种不同统计汇总
g_07[['P','K']].agg(dict(
    P=[('最大值', np.max), ('最大值', np.max), ('最小值', np.min), ('平均值', np.mean)],
    K=[('计数', pd.Series.count), ('中位数', np.median)]
))
#%% md
##  透视表pivot_table
#%%
df_01.pivot_table(
    values=['P', 'K', 'T'],  # 需要透视分组的列
    index=['cls', 'sex'],  # 需要透视的指标
    aggfunc=dict(  # 聚合运算
        P=[('最小值', np.min)],
        K=[('最大值', np.max), ('中位数', np.median)],
        T=[('最小值', np.min), ('平均值', np.mean), ('计数', len)]
    )
).round(0)
#%%

在这里插入图片描述

这是一份Pandas优质课的教案,适用于初学者和有一定基础的学习者。以下是教案大纲: ## 课程概述 - Pandas简介 - Pandas基础数据结构 - 数据操作与清洗 - 数据分析与可视化 ## 课程目标 - 理解Pandas基本数据结构,如Series和DataFrame - 掌握Pandas常用的数据操作和清洗方法 - 能够使用Pandas进行数据分析和可视化 ## 课程大纲 ### 第一课:Pandas简介 - Pandas是什么 - Pandas的优势和应用场景 - Pandas的基本数据结构 ### 第二课:Pandas基础数据结构 - Series的创建和操作 - DataFrame的创建和操作 - 索引和选取 ### 第三课:数据操作与清洗 - 缺失值处理 - 数据类型转换 - 数据合并和拼接 - 数据分组聚合 ### 第四课:数据分析与可视化 - 数据分析 - 数据可视化 ## 课程细节 - 课程时长:4周,每周2小时 - 授课方式:线上授课 - 作业和实践:每周布置1-2个作业和实践任务,需在截止日期前提交 - 考核方式:期末考试和项目作品 ## 授课方法 - 理论讲解:通过PPT和实例,讲解Pandas基础知识和操作方法 - 实践演练:通过实际案例演示,帮助学生掌握Pandas的应用场景和具体操作方法 - 互动答疑:通过QQ群或微信群,及时回答学生提出的问题和疑惑 ## 考核要求 - 期末考试:考查学生对Pandas基础知识和操作方法的掌握程度 - 项目作品:要求学生在选定的数据集上,进行数据分析和可视化,并撰写项目报告和代码 ## 参考资料 - Pandas官方文档:https://pandas.pydata.org/docs/ - 《利用Python进行数据分析》 - 《Python数据科学手册》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CY3761

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值