Pandas.DataFrame.groupby() 数据分组(数据透视、分类汇总) 详解 含代码 含测试数据集 随Pandas版本持续更新 您所在的位置:网站首页 excel如何分组汇总函数数据分析 Pandas.DataFrame.groupby() 数据分组(数据透视、分类汇总) 详解 含代码 含测试数据集 随Pandas版本持续更新

Pandas.DataFrame.groupby() 数据分组(数据透视、分类汇总) 详解 含代码 含测试数据集 随Pandas版本持续更新

2024-07-14 11:01| 来源: 网络整理| 查看: 265

关于Pandas版本: 本文基于 pandas2.2.0 编写。

关于本文内容更新: 随着pandas的stable版本更迭,本文持续更新,不断完善补充。

传送门: Pandas API参考目录

传送门: Pandas 版本更新及新特性

传送门: Pandas 由浅入深系列教程

本节目录 Pandas.DataFrame.groupby()语法:返回值:参数说明:by 指定分组依据axis 指定分割方向level 指定多层索引的层级编号或层级名称as_index 排序方法(升序或降序)sort 是否对组名排序group_keys 是否返回组键observed 只显示观测值或显示所有值dropna 其他排序置 相关方法:示例:

Pandas.DataFrame.groupby()

DataFrame.groupby() 方法用于使用映射器或指定的列,对 DataFrame 进行数据分组,可以实现类似Excel的数据透视、分类汇总的效果。

DataFrame.groupby() 的底层逻辑是:

1、根据指定的规则(由 by 参数指定)分割 DataFrame 为 groupby 对象; 此时只是完成了 DataFrame 分割,仅仅是一个 groupby 对象,还没有完成汇总。这意味着无法像观察 DataFrame 一样观察它:可以使用 for 循环观察groupby 对象。 例1用于分组的分类内容,默认会作为这个新 DataFrame 的索引(行索引,或列名,具体视汇总方向而定)。例2-5 2、应用指定的方法,汇总、聚合被分割的数据。 如果应用一种汇总计算方法,所有列都是用一种汇总方法进行聚合。例2也可以通过 DataFrame.agg 指定不同的列使用不同的计算方法作为汇总方式。例2-4 3、应用聚合方法之后,DataFrame.groupby() 会自动的将聚合后的数据合并为新的 DataFrame。

⚠️ 注意:

1、数据分割实际上是基于行索引进行的。

2、你指定的分割依据(分组依据)需要尽可能的,和行索引等长。

数据分组流程示意图

数据分组流程示意图 语法:

DataFrame.groupby (by=None, axis=_NoDefault.no_default, level=None, as_index=True, sort=True, group_keys=True, observed=_NoDefault.no_default, dropna=True)

返回值: pandas.api.typing.DataFrameGroupBy 返回包含分组信息的 groupby 对象。 参数说明: by 指定分组依据

**by:**mapping, function, label, pd.Grouper or list of such

by 参数用于指定分组的依据(即分割DataFrame的依据):

label(列名):用于把某列指定为分组依据

当某列的数据具有分类特性,指定这个列的列名,作为分组依据 DataFrame 。例1

mapping(映射):用于直接把行索引的值指定为分组依据

dict(字典):适用于行索引的值可以拿来做分组(常用于分组名称的重命名) 例3 传递一个字典,字典的键是行索引里的可以作为分组的值,字典的值你自定义的分组名; 注意!如果只传递字典,你需要提前准备好行索引。并且行索引里的值,应该是可以有效分组的。 Series(序列):适用于你有一个和 DataFrame 行索引等长的 Series时 例4 这个 Series 里的值,应该是可以有效分组的;这个 Series 建议和 DataFrame 行索引等长;如果这个Series 必须和 DataFrame 行索引不等长,会自动进行对齐(.align()),二者数据量如果差距太大,会产生很多缺失值,造成分组后计算不精准的结果。

function(函数): 函数将作用于行索引的每个值,并使用处理后的值,作为分组依据。 例5

行索引中被函数处理后的值,并不会影响计算前的 groupby 对象。例5-1行索引中被函数处理后的值,将展示在完成分组计算,合并后的 DataFrame。例5-2

pd.Grouper:通常用于按照时间间隔分组,直接作用于行索引 例6

list of such:多个列构成多维度分组汇总

列名列表: 常用于多维度分组汇总,列表里的第1个列名,默认作为顶层行索引,和其他列名构成多层索引。 例7 axis 指定分割方向

axis: {0 or ‘index’, 1 or ‘columns’}, default 0

axis 参数用于指定分割方向(可以参照此图,了解什么是分割 数据分组流程示意图):

0 or ‘index’: 默认为按行索引分割。1 or ‘columns’: 按列分割。

⛔ 弃用于 Pandas 2.1.0 :

axis=1 在 Pandas 2.1.0 版本标记为弃用。使用以下替代方法实现:

先 转置 再 分组 frame.T.groupby(...) 例8

这样做的目的是:使分组后数据尽可能的保持更多的操作性和可读性。

level 指定多层索引的层级编号或层级名称

level: int, level name, or sequence of such, default None 例9

如果 DataFrame 具有多层索引,可以用level参数指定级别的编号或名称,不能和 by 参数同时使用。

int:整数层级编号 可以用 整数层级编号 指定分组依据。例9-2level name:层级名称 可以用层级名称, 指定分组依据。例9-2sequence of such:层级编号列表,或层级名称列表 可以用层级编号列表,或层级名称列表指定多个分组依据,类似于 by 参数传递列名列表。例9-3 as_index 排序方法(升序或降序)

as_index: bool, default True 例10

as_index 参数控制是否将组标签作为索引返回。

当 as_index=True 时,组标签将成为输出 DataFrame 的索引。当 as_index=False 时,组标签不会成为索引,而是返回一个类似 SQL 风格的输出。 sort 是否对组名排序

sort: bool, default True 例11

sort 参数用于控制是否对分组名进行排序,默认 sort=True 会对组名进行排序。此参数不会影响每个组内观察值的顺序:

True: 对分组名进行排序。False: 关闭分组名排序,如果关闭,则组将按其在原始 DataFrame 中的顺序显示,可以获得更高的性能。

📌 改动于 Pandas 2.0.0 :

自 Pandas2.0.0 开始,当使用 有序分类 数据进行分组,当 sort=False 将不再对其进行排序。

在之前的版本中(2.0.0 之前),即使设置了 sort=False,对于有序分类,仍然会对分类进行排序。而在 2.0.0 版本中,这个行为发生了变化,即设置 sort=False 不再影响有序分类的排序,保留原始顺序。

这个改动的目的是为了提供更一致的行为,使得在使用 sort=False 时,无论分类是否有序,都不再对分类进行排序,从而减少用户的困惑。

group_keys 是否返回组键

group_keys: bool, default True

分组的键指的是 groupby 对象 各分组的行索引。

当使用 groupby 调用 apply 与 by 参数生成分组结果时, 并且 结果行索引数量 和 groupby 对象分组数量 不匹配(不匹配则意味着无法汇总),则默认会将 groupby 对象各分组的行索引 和 结果行索引 组合为多层行索引,以便观察。 例12

当 group_keys=True 时(默认值),分组的键会作为结果的索引。这意味着返回的对象会是一个带有分组键的多层次索引的 DataFrame(或者 Series,具体取决于你应用 groupby 的对象是 DataFrame 还是 Series)。当 group_keys=False 时,分组的键不会作为索引,而是返回一个不带有分组键的普通 DataFrame(或者 Series)。 例12-3

📌 **改动于 Pandas 1.5.0 :

当使用 groupby 调用 apply 与 by 参数生成分组结果时,并且结果行索引数量 和 groupby 对象分组数量 不匹配(不匹配则意味着无法汇总),则需要显式指定 group_keys 是否包含组键。

📌 **改动于 Pandas 2.0.0 :

group_keys 默认为 True。

observed 只显示观测值或显示所有值

observed: bool, default False

观察值是指在实际数据中存在的唯一分类值。当应用 groupby 操作时,有时可能会遇到分类分组器中存在的分类值,但在实际数据中并未出现的情况。observed 参数允许你控制在分组操作中如何处理这些未观察到的分类值:

True: 只显示分类分组器(groupers)的观察值(observed values),而不显示未观察到的值。False: 则显示所有分类分组器的可能值,包括未在实际数据中观察到的值。

⛔ 弃用于 Pandas 2.1.0 :

自2.1.0版本以来已弃用:在panda的未来版本中,默认值将更改为True。

dropna 其他排序置

dropna: bool, default True 例13

dropna 用于控制 groupby 对象的行数索引是否可以包含缺失值:

如果为 True,并且组键包含缺失值,则将 缺失值与行/列一起删除。如果为 False,则保留缺失值。

⚠️ 注意 :

舍弃缺失值的动作,是在分组前完成的,也就是说,在生成 groupby 分组对象的时候,就已经没有缺失值了。例13-2

相关方法:

➡️ 相关方法

resample

Convenience method for frequency conversion and resampling of time series.

示例:

测试文件下载:

本文所涉及的测试文件,如有需要,可在文章顶部的绑定资源处下载。

若发现文件无法下载,应该是资源包有内容更新,正在审核,请稍后再试。或站内私信作者索要。

测试文件下载位置.png

例1:如果没有指定聚合计算方法,分组结果将是一个 groupby 对象,只能通过 for 循环观察数据内容

例1-1、准备演示数据 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员季度销售额.xlsx") # 观察数据内容 df.sample(5) 姓名片区1季度2季度3季度4季度year18邹小琴华南403860534691117820234左美华华南579294434087365202384祝成云华东1186315519751922202347紫薇华北1728480218576988202340邹博文华北34345814133490612023 例1-2、用 片区列 分组,但是不传递聚合计算方法 grouped = df.sample(5).groupby(by="片区") grouped

由上面结果可以发现,无法直接观察 GroupBy 对象

例1-3、使用 for 循环观察分组内容 for group_name, group_data in grouped: print(f"Group: {group_name}") print(group_data) print("\n") Group: 华中 姓名 片区 1季度 2季度 3季度 4季度 year 73 庄海彬 华中 2534 968 4128 5454 2023 59 卓小珍 华中 3274 5837 3025 7993 2023 Group: 华北 姓名 片区 1季度 2季度 3季度 4季度 year 95 张华丽 华北 4584 1072 3029 8976 2023 48 紫湉 华北 3046 3918 6908 6444 2023 Group: 华南 姓名 片区 1季度 2季度 3季度 4季度 year 97 王娟 华南 661 6784 3660 8621 2023

例2:分组后,指定汇总计算方式,即可自动完成最终的合并过程,并生成新的 DataFrame

例2-1、构建演示数据并观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员季度销售额.xlsx") # 观察数据内容 df.sample(5) 姓名片区1季度2季度3季度4季度year71庄骏华中4713258864806224202327邹立文华北1547492746938526202338邹凤艳华北205553306468722920230左院梅华南1491108350009461202377祝艳斌华东51611639129175282023

例2-2、以片区列 作为分组依据,只传递一种求和的计算方法。 grouped = df.groupby(by="片区").sum() grouped 姓名1季度2季度3季度4季度year片区华东转身,泪倾城筑梦祝艳斌祝艳祝小娟祝仙花祝卫平祝玛拉初祝海英祝成云竹林听雨竹合竹猪哥传说诸子燕...5372062152771858527136414华中梓英籽艺子鱼子墨子岚子和子菡资格卓越卓小珍卓向吴追影追忆追梦状之元巍笑吧庄臻庄永奇庄晓运庄...8624911993411950115388954621华北邹美金邹灵美邹林华邹立文邹黎邹娟利邹杰邹建军邹建华邹吉宏邹积杰邹海利邹贵滨邹广坤邹凤艳邹昌乐...7277612546712000218655058667华南左院梅左艳艳左薇左娜左美华左梅香左火英左儿左成娟醉霖~棉花糖最终幻想走向幸福邹邹邹子龙邹忠珠...608221096548934214389652598

以片区为分组依据,并传递了求和方法后,姓名列因为是字符串,所以相当于拼接。1季度、2季度、3季度、4季度、year等列,完成了求和计算。

例2-3、指定计算方法,作为汇总方式,即可观察数据分组后的数据了。 grouped = df.groupby(by="片区").sum() grouped 姓名1季度2季度3季度4季度year片区华东转身,泪倾城筑梦祝艳斌祝艳祝小娟祝仙花祝卫平祝玛拉初祝海英祝成云竹林听雨竹合竹猪哥传说诸子燕...5372062152771858527136414华中梓英籽艺子鱼子墨子岚子和子菡资格卓越卓小珍卓向吴追影追忆追梦状之元巍笑吧庄臻庄永奇庄晓运庄...8624911993411950115388954621华北邹美金邹灵美邹林华邹立文邹黎邹娟利邹杰邹建军邹建华邹吉宏邹积杰邹海利邹贵滨邹广坤邹凤艳邹昌乐...7277612546712000218655058667华南左院梅左艳艳左薇左娜左美华左梅香左火英左儿左成娟醉霖~棉花糖最终幻想走向幸福邹邹邹子龙邹忠珠...608221096548934214389652598

例2-4、不同的列指定不同的汇总方式,没有指定汇总方式的列,不会出现在汇总结果。例如 姓名列。 grouped = df.groupby(by="片区").agg( {"1季度": "max", "2季度": "mean", "3季度": "sum", "4季度": "min"} # 最大值 # 平均值 # 总和 ) # 最小值 grouped 1季度2季度3季度4季度片区华东51613452.888889771851066华中53084442.0000001195011684华北45844326.4482761200021136华南50704217.461538893421055

例2-5、用于分组的分类数据,在完成数据分组后,会作为索引使用(行索引或列名,具体视分组方向而定) grouped.axes [Index(['华东', '华中', '华北', '华南'], dtype='object', name='片区'), Index(['1季度', '2季度', '3季度', '4季度'], dtype='object')]

例3:使用字典数据分组(直接把行索引里的值用字典的方式,指定为分组依据)

例3-1、构建演示数据并观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员季度销售额.xlsx") # 将 片区列,设置为索引 df.set_index("片区", inplace=True) # 观察数据内容 df.sample(5) 姓名1季度2季度3季度4季度year片区华东李先锋40574953677617232023华南邹小琴40386053469111782023华中子墨33931562360772732023华北邹娟利38402815655132172023华南邹秀珍32051772153469952023 例3-2、 by 参数传入字典,字典的键是 DataFrame 行索引里的值,字典的值是分组名; grouped = df.groupby(by={"华东": "东部战区", "华南": "南部战区", "华北": "北部战区", "华中": "中部战区"}).agg( {"1季度": "max", "2季度": "mean", "3季度": "sum", "4季度": "min"} # 最大值 # 平均值 # 总和 ) # 最小值 grouped 1季度2季度3季度4季度片区东部战区51613452.888889771851066中部战区53084442.0000001195011684北部战区45844326.4482761200021136南部战区50704217.461538893421055

例4:使用Series数据分组(用Series替换当前行索引,并使用里面的值作为分组依据)

例4-1、构建演示数据并观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员季度销售额.xlsx") # 观察数据内容 df.sample(5) 姓名片区1季度2季度3季度4季度year60卓向吴华中4713169123989270202343自在华北2354460559288614202363追梦华中2689679042477637202317邹秀珍华南3205177215346995202342自在小英华北21002230340935722023 例4-2、使用Series,构建数据分组。(为了方便,我们把片区列拿过来作为Series做演示) # 提取片区列作为Series s = df["片区"].copy(deep=True) # 使用Series,构建数据分组 grouped = df.groupby(by=s).max() grouped 姓名片区1季度2季度3季度4季度year片区华东转身,泪倾城华东51616753677692842023华中邹世军华中53087377720492702023华北邹黎华北45847421694592302023华南醉霖~棉花糖华南50707412597194612023

例5:使用函数数据分组(函数将作用于行索引的每个值)

例5-1、构建演示数据并观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员季度销售额.xlsx") # 将 片区列,设置为索引 # df.set_index('片区',inplace=True) # 观察数据内容 df.sample(5) 姓名片区1季度2季度3季度4季度year38邹凤艳华北2055533064687229202335邹海利华北3875579940578344202383祝海英华东1018143048457155202392邹世军华中4343486627437617202311走向幸福华南43122189443174932023

例5-1、当前行索引是自然索引,我想按照行索引的单数、双数进行分组,可以这样做: # 定义区分单数双数的函数 def rename_index(index): if index % 2 == 0: return "双数" else: return "单数" # 应用这个函数,处理行索引进行分组 grouped = df.sample(12).groupby(by=rename_index) # 查看group对象里的内容 for group_name, group_data in grouped: print(f"Group: {group_name}") print(group_data) print("\n") Group: 单数 姓名 片区 1季度 2季度 3季度 4季度 year 37 邹广坤 华北 3015 5912 2120 3750 2023 77 祝艳斌 华东 5161 1639 1291 7528 2023 97 王娟 华南 661 6784 3660 8621 2023 89 诸子燕 华东 2454 1824 3306 4198 2023 79 祝小娟 华东 4419 6753 2838 1066 2023 11 走向幸福 华南 4312 2189 4431 7493 2023 63 追梦 华中 2689 6790 4247 7637 2023 Group: 双数 姓名 片区 1季度 2季度 3季度 4季度 year 34 邹积杰 华北 2175 4902 4874 3110 2023 92 邹世军 华中 4343 4866 2743 7617 2023 8 左成娟 华南 1747 5823 1480 7025 2023 76 筑梦 华东 1856 3905 5808 6265 2023 98 刘贤 华东 3960 6437 3148 1517 2023

从上面这个结果可以发现,函数处理并没有影响到 groupby 对象

例5-2、函数处理行索引的结果,会展现在汇总计算后,合并的新 DataFrame 里 # 给分组对象一个计算方式,完成最终数据合并,并观察 grouped.max() 姓名片区1季度2季度3季度4季度year单数邹广坤华南51616790443186212023双数邹积杰华南43436437580876172023

从上面可以发现,如果 by 参数传递了函数,被修改的 行索引 只会作为分组依据、和分组名称,出现在汇总计算后,合并的新 DataFrame 里。

例6:使用pd.Grouper分组

例6-1、构建演示数据并观察数据内容 from datetime import datetime import numpy as np import pandas as pd # 创建一个包含时间序列的DataFrame date_rng = pd.date_range(start="2022-01-01", end="2022-01-19", freq="D") df = pd.DataFrame(date_rng, columns=["date"]) # 添加一列随机数值 df["value"] = np.random.randn(len(date_rng)) # 观察数据内容 df datevalue02022-01-010.63277112022-01-021.21829222022-01-03-0.86425132022-01-040.62820442022-01-05-0.62545452022-01-061.02108162022-01-070.68550972022-01-081.09675482022-01-09-1.13197992022-01-100.384067102022-01-110.447377112022-01-120.005861122022-01-131.126507132022-01-14-0.153360142022-01-150.447708152022-01-160.470841162022-01-17-1.143815172022-01-18-0.407859182022-01-190.308274 例6-2、构建以‘周’为周期的grouper对象,并观察其数据内容 # 创建grouper对象 grouper = pd.Grouper(key="date", freq="W") grouper TimeGrouper(key='date', freq=, axis=0, sort=True, dropna=True, closed='right', label='right', how='mean', convention='e', origin='start_day') 例6-3、按周进行分组,求每周的均值 # 按轴分组,并计算每组的均值 result = df.groupby(grouper).mean() result valuedate2022-01-020.9255322022-01-090.1156952022-01-160.3898572022-01-23-0.414467

例7:by参数传递列名列表,构成多层索引,作为多维度的数据汇总

例7-1、构建演示数据并观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员日销售额.xlsx") # 只保留需要的列 df = df[["职级", "片区", "业绩"]] # 观察数据内容 df.sample(5) 职级片区业绩82经理华中14494.914经理华南27318.567组长华东843.322经理华南853.843组长华北545.8 例7-2、传递列名列表,多维度数据分组汇总。观察各职级销售人员,在不同地区的销售表现 df.groupby(by=["职级", "片区"]).sum() 业绩职级片区组长华东17526.0华中4043.1华北6524.8经理华东148805.5华中125646.0华北58211.8华南1067600.6销售员华东7896.9华中11233.6华北1772.2华南8281.1

例8:先转置再分割,实现类似纵向分割 axis=1 的效果

例8-1、读取演示数据并观察内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员日销售额_用于转置.xlsx") # 观察数据内容 df Unnamed: 0012345678...909192939495969798990职级销售员经理经理销售员销售员销售员销售员销售员销售员...经理经理销售员组长销售员销售员销售员经理销售员销售员1片区华南华南华南华南华南华南华南华南华南...华中华中华中华中华中华中华中华中华中华中2业绩523.916647.5825896.91051.1672.51542.2540.9752.5585...18261808968251112.9888.7721.3941.317740.2692.11165.2

3 rows × 101 columns

可以发现,在这个演示数据中,如果需要分组,则需要 axis=1 , 但是这不符合Pandas新版本特性。

例8-2、先转置,再用片区分组 df.T.groupby(by=1).max() 021华东销售员99327.4华中销售员18261华北销售员9388华南销售员825896.9片区职级业绩

分组完毕,by=1 是因为片区的哪一列,此时列名就是1

例9:多层索引需要使用 level 参数传递层级信息指定分组依据

例9-1、读取演示数据,构建多层索引,观察数据内容 import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员日销售额.xlsx") # 只保留需要的列 df = df[["职级", "片区", "业绩"]] # 构建多层索引 df.set_index(["片区", "职级"], inplace=True) # 观察数据内容 df.sample(5) 业绩片区职级华中经理1459.4华南销售员540.9销售员773.4华中经理744.0组长1304.8

例9-2、 只使用片区作为分组依据,则只需要传递层级编号,或层级名称即可。 df.groupby(level="片区").sum() 业绩片区华东174228.4华中140922.7华北66508.8华南1075881.7 df.groupby(level=0).sum() 业绩片区华东174228.4华中140922.7华北66508.8华南1075881.7

例9-3、 如果需要使用多列内容,使用列表传递层级编号或层级名称即可(可以混用) df.groupby(level=[0, "职级"]).sum() 业绩片区职级华东组长17526.0经理148805.5销售员7896.9华中组长4043.1经理125646.0销售员11233.6华北组长6524.8经理58211.8销售员1772.2华南经理1067600.6销售员8281.1

例10:分组名称不再作为索引,使用SQL风格展示分组后的数据

import pandas as pd # 读取一个演示文件 df = pd.read_excel("../../../../数据集/团队成员日销售额.xlsx") # 只保留需要的列 df = df[["职级", "片区", "业绩"]] df # 用片区进行分组,并关闭索引返回 df.groupby(by="片区", as_index=False).max() 片区职级业绩0华东销售员99327.41华中销售员18261.02华北销售员9388.03华南销售员825896.9

由上面结果可以发现,片区列,没有再作为行索引。

例11:sort参数对分组结果的影响

例11-1、默认情况下,数据分组后输出的 DataFrame 会开启组名排序 import pandas as pd # 构建演示数据 df = pd.DataFrame({"cat": ["b", "b", "a", "a"], "value": [1, 3, 2, 4]}) # 用cat列构建分组,保持分组名排序开启, grouped = df.groupby(by="cat").mean() grouped valuecata3.0b2.0 例11-2、 当 sort=False 数据分组后输出的 DataFrame 不再对组名排序 # 用cat列构建分组,关闭分组名排序 grouped2 = df.groupby(by="cat", sort=False).mean() grouped2 valuecatb2.0a3.0

例12:应用apply,如果结果行数 > 分组数量,则无法完成汇总,各分组的行索引(组键)会和分组名组成多层索引

例12-1、首先来观察以下,各个分组的行索引 import pandas as pd # 构建演示数据 df = pd.DataFrame({"cat": ["b", "b", "a", "a"], "value": [1, 3, 2, 4]}) # 用cat列构建分组,保持分组名排序开启, grouped = df.groupby(by="cat") # 打印每个组的内容 for name, group in grouped: print(f"Group {name}:") print(group) print("\n") Group a: cat value 2 a 2 3 a 4 Group b: cat value 0 b 1 1 b 3

留意上面结果,a和b两个分组的行索引2、3、0、1。

例12-2、当 调用 apply ,但是结果行数 > 分组数量时,会产生由分组名、各分组行索引构成的多层索引, import pandas as pd # 构建演示数据 df = pd.DataFrame({"cat": ["b", "b", "a", "a"], "value": [1, 3, 2, 4]}) # df['cat'] = df['cat'].astype('category') # 用cat列构建分组,保持分组名排序开启, grouped = df.groupby(by="cat").apply(lambda x: x) grouped catvaluecata2a23a4b0b11b3

例12-3、 当 group_keys=False 时,分组的键不会作为索引,而是返回一个不带有分组键的普通 DataFrame(或者 Series)。 import pandas as pd # 构建演示数据 df = pd.DataFrame({"cat": ["b", "b", "a", "a"], "value": [1, 3, 2, 4]}) # df['cat'] = df['cat'].astype('category') # 用cat列构建分组,保持分组名排序开启, grouped = df.groupby(by="cat", group_keys=False).apply(lambda x: x) grouped catvalue0b11b32a23a4 例12-4、再来看一下,正常应该是什么样的 import pandas as pd # 构建演示数据 df = pd.DataFrame({"cat": ["b", "b", "a", "a"], "value": [1, 3, 2, 4]}) # df['cat'] = df['cat'].astype('category') # 用cat列构建分组,保持分组名排序开启, grouped = df.groupby(by="cat").apply(lambda x: x.mean()) grouped valuecata3.0b2.0

例13:组键(分组名、或可理解为结果的行索引、也可以理解为各分组的行索引)缺失值处理

例13-1 构建演示数据并观察 import pandas as pd # 构建演示数据 l = [["a", 12, 12], [None, 12.3, 33.0], ["b", 12.3, 123], ["a", 1, 1]] df = pd.DataFrame(l, columns=["a", "b", "c"]) df abc0a12.012.01None12.333.02b12.3123.03a1.01.0

例13-2 在分组完成时,默认就已经舍弃了缺失值 grouped = df.groupby(by="a") # 打印每个组的内容 for name, group in grouped: print(f"Group {name}:") print(group) print("\n") Group a: a b c 0 a 12.0 12.0 3 a 1.0 1.0 Group b: a b c 2 b 12.3 123.0

由上面结果可以发现,当完成分组的时候,就已经没有缺失值了,这一步发生在合并每个分组产生结果之前。

例13-3 dropna=True 可以保留缺失值 grouped = df.groupby(by="a", dropna=False).mean() grouped bcaa6.56.5b12.3123.0NaN12.333.0


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有