![Python大数据与机器学习实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/134/30638134/b_30638134.jpg)
3.3 分组运算
分组运算(Groupby)是指按某一特征(字段)将一个大数据表分成几张小表,分表后经过统计处理再将结果重组。分组操作极大地简化了数据处理的流程,并提高了处理效率。
3.3.1 分组
本小节先从一个实例开始,实例使用1996年美国大选的数据集。首先载入数据集,并查看数据的基本情况。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_1.jpg?sign=1739086265-T62DkTudAds0cEtMHPPctADQdyvkwwbA-0-7fc0a83117f5b8095b8a3762fe5bbfec)
数据基本情况如表3.2所示,可以看到表中多数列为类别(枚举)类型。
表3.2 美国大选数据集前五行数据
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_2.jpg?sign=1739086265-f0fhPxzSFH3Cci20jKEyMjeaSvSsBVAh-0-0c7f86fdc427ca5c35719978b2659f33)
分组既可以对Series分组,也可以对DataFrame分组,支持使用一个特征及多个特征作为分组条件。当使用“受教育程度”分组时,数据被分为七组,每种受教育程度相同的记录被分成一组;按“受教育程度”和“投票”两个特征分组时,数据表被分成14个组,每种特征的组合分为一组。另外,还可以使用lambda表达式作为分组依据。下例中按索引值奇偶将数据分成两组。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_3.jpg?sign=1739086265-RPssUxV1lqjrCbBb4CnwKvUahSSyAiNp-0-ecd77f39761501aeb4eda8132a15a219)
执行groupby命令后数据并未被真正拆分,只是在访问组中的数据时才会执行拆分操作,这会使得分组操作变得快速且节约存储空间。
使用get_group方法可获取某一组中的所有记录。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_4.jpg?sign=1739086265-f8y8anjrE08tPWFlMqWhsTLhRaCeIl1y-0-d063d93140c261837fd98827ae9c482e)
一般通过迭代方式访问分组元素,其中desc为分组的特征值,item是包含该组中的所有记录的新数据表。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_1.jpg?sign=1739086265-WHpAQWbnAcFuPb4FTH3Som8Z7QLgGvcb-0-686e935c5391a78e5333354a38600d83)
使用字段名作为下标可获得只包含该字段的新组,用这种方式可实现依据某一列给另一列分组,以供后续计算。下例中按vote分组后取每组的age,迭代方式访问的元素item是Series类型,其中包含该组中的所有age值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_2.jpg?sign=1739086265-x6vVDHSNkJnkNagqhuOB25tdyi9o2DcP-0-e50328071bb96c87ea0cd689a88375aa)
统计分组后的数据也是常用的操作,如统计为不同候选人投票的两组的人数和平均年龄,方法如下例所示。除了计数和求平均值,也可以使用求和、求中值等其他统计方法。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_3.jpg?sign=1739086265-wL4KMn4sAtejnscjYxQqa2SANvi9bkQW-0-e9caa8ba6a4e4d6f2de756a95181fbab)
上例中返回值的类型为Series,分组变量的取值为索引值,组中元素个数为value。还可以利用reset_index方法将结果转换成单层索引的DataFrame,其中分组变量vote和年龄均值age都已转换成新数据表中的字段。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_4.jpg?sign=1739086265-j7DW2gX8oF18qqZhoDwln9PzdiXojEf3-0-bb91dd37db5412dd168de2606dfeecfa)
3.3.2 聚合
聚合(Agg)可以对每组中的数据进行聚合运算,即把多个值按指定方式转换成一个值。Agg的参数是处理函数,它将列中的数据转给处理函数,为方便理解,还是从实例开始。本例中使用statsmodels中自带的信用卡数据,数据非常简单,只有五个字段。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_1.jpg?sign=1739086265-50mtkMzIkZ7HNUZUF68qawyH279WxEhS-0-73d23f3443624a506dd47891fcb8473a)
使用OWNRENT值分组,由于它的取值为0或1,因此数据被分为两组,用集合方法调用取平均值的函数来聚合数据。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_2.jpg?sign=1739086265-ABoG9huqEMaMSeIBjM9UqsIAuJlnF558-0-84eb96cc033a38833972a9a6a6aac094)
返回结果也是DataFrame对象。转换后的字段和原表相同,记录变为两个,分别对应不同的分组,表中的数据是该字段不同组的均值。本例中使用了Numpy的均值函数,也可用自定义函数,或者使用lambda表达式定义处理方法,如下例中将每组中收入最高的记录作为变换后的值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_3.jpg?sign=1739086265-2VYTvJMzZ9h0TwwM7vRlZwPzFQHJuBVQ-0-d4b9049d73c97b73b7d4f23c490ab80a)
3.3.3 转换
转换(Transform)是将数据表中的每个元素按不同组进行不同的转换处理,转换之后的行索引和列索引不变,只有内容改变。下例中将收入(INCOME)的实际值转换为INCOME减去该组的均值,用于表示其收入在所属组中是偏高还是偏低。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_4.jpg?sign=1739086265-D14llhuWKvH4trXSjuchrCPRyTLcDF20-0-ff9c0a216fd4976181b354ebb3b002f3)
聚合和转换都支持将DataFrame和Series作为输入。上例中将DataFrame作为处理对象,输出的是DataFrame;本例中将Series作为处理对象,转换后输出的也是Series。
3.3.4 过滤
过滤(Filter)是通过一定的条件从原数据表中过滤掉一些数据,过滤之后列不变,行可能减少,具体方法是按组过滤,即过滤掉某些组。
本例中,使用lambda函数过滤掉了收入(INCOME)均值小于3的组。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_88_2.jpg?sign=1739086265-bL4iKyp90c1zdOcvBD2L7C0v6bNoPZqY-0-08f48dee625d22e412eb8bbb50038e4e)
处理函数接收的参数是某一分组中的所有数据,返回布尔值。当布尔值为True时保留该组,当布尔值为False时过滤掉该组,判断条件一般是根据组中数据求出的统计值。
3.3.5 应用
相对于前几种方法,应用(Apply)更加灵活,并且能实现前几种处理的功能。其处理函数的输入是各组的DataFrame,返回值可以是数值、Series,DataFrame,apply会根据返回的不同类型构造不同的输出结构。
用apply实现聚合功能:
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_88_3.jpg?sign=1739086265-POB8NJESc2BTP3N8BXKyh1xr1YBjVsLO-0-3e2be9715af07bd5603fe7ad4e1eaff1)
用apply实现转换功能:
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_88_4.jpg?sign=1739086265-2h8cFtVpzZ25lGXA7YlhFmk2CNfSVb7m-0-756841970691581442fe5c6cb4657d56)
用apply实现过滤功能与使用filter函数不同的是,当满足条件时,返回df;当不满足条件时,返回None,即在重组时忽略该返回值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_89_1.jpg?sign=1739086265-XTAwuBZf38XUTRTroyo745iqEbh7INOZ-0-e4be1b1a772ab33adc203076e59ca374)
除以上功能外,apply还提供更灵活的使用方式,比如返回符合条件组中的前N条。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_89_2.jpg?sign=1739086265-E8uPdCPdHEsNvqMA5O4UFojh3g9ZQRL8-0-72ef76d9c15333de61520d7327120468)
Pandas对常用的聚合功能在底层做了优化,使apply函数的速度比自行分组计算之后再组合快得多,因此其是数据处理中不可或缺的工具。