![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=1739520954-BNjZlfv2mhDGknDS3CmVr5fQlA6WGnFb-0-ff527d35d0e59da9e9ade51ff9e4e8b3)
数据基本情况如表3.2所示,可以看到表中多数列为类别(枚举)类型。
表3.2 美国大选数据集前五行数据
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_2.jpg?sign=1739520954-hW1NwgakfWOpWsj8VAjUCUnPYm7Dj1Lt-0-09e3b503a658c3884e7f976ef6a340e8)
分组既可以对Series分组,也可以对DataFrame分组,支持使用一个特征及多个特征作为分组条件。当使用“受教育程度”分组时,数据被分为七组,每种受教育程度相同的记录被分成一组;按“受教育程度”和“投票”两个特征分组时,数据表被分成14个组,每种特征的组合分为一组。另外,还可以使用lambda表达式作为分组依据。下例中按索引值奇偶将数据分成两组。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_3.jpg?sign=1739520954-fcRrMz6wq29Aju0dZULkbohDBFVf2wC0-0-d125ca30fa45994667b555b1b7ce7efc)
执行groupby命令后数据并未被真正拆分,只是在访问组中的数据时才会执行拆分操作,这会使得分组操作变得快速且节约存储空间。
使用get_group方法可获取某一组中的所有记录。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_85_4.jpg?sign=1739520954-Ioh32KGlsPeZD4JU9E2LalAl07OBFbtK-0-e20b682a7e4612698ab9b241eaa40086)
一般通过迭代方式访问分组元素,其中desc为分组的特征值,item是包含该组中的所有记录的新数据表。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_1.jpg?sign=1739520954-Gy1N5yvtKn5R1n83V3MQpSiMqCTjqXRy-0-5968914fc9ba4e3e0eab593e17f82579)
使用字段名作为下标可获得只包含该字段的新组,用这种方式可实现依据某一列给另一列分组,以供后续计算。下例中按vote分组后取每组的age,迭代方式访问的元素item是Series类型,其中包含该组中的所有age值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_2.jpg?sign=1739520954-AAk0yLrC4ZMklVf2heJPuUhLEFhmQsmD-0-60756bed790496aa793db9747ff60126)
统计分组后的数据也是常用的操作,如统计为不同候选人投票的两组的人数和平均年龄,方法如下例所示。除了计数和求平均值,也可以使用求和、求中值等其他统计方法。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_3.jpg?sign=1739520954-2r93rVxV5MdcwUKfYDlONCkKPsAnqEPm-0-d7fa02100017925e3490658bcd96cf8c)
上例中返回值的类型为Series,分组变量的取值为索引值,组中元素个数为value。还可以利用reset_index方法将结果转换成单层索引的DataFrame,其中分组变量vote和年龄均值age都已转换成新数据表中的字段。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_86_4.jpg?sign=1739520954-rbQi9b3lCQuEbfZrGY0bDGbBsxKVwP1B-0-8529ec765a982f2f5f3eef47b57e4cda)
3.3.2 聚合
聚合(Agg)可以对每组中的数据进行聚合运算,即把多个值按指定方式转换成一个值。Agg的参数是处理函数,它将列中的数据转给处理函数,为方便理解,还是从实例开始。本例中使用statsmodels中自带的信用卡数据,数据非常简单,只有五个字段。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_1.jpg?sign=1739520954-qPwLc61vDb4B5oU4pP5jxOdJT3cwDm7I-0-b20e896ad988e1ca7314621abd4cd272)
使用OWNRENT值分组,由于它的取值为0或1,因此数据被分为两组,用集合方法调用取平均值的函数来聚合数据。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_2.jpg?sign=1739520954-H53ykXSvkm25yBphfIhY408ZLdYMgAE0-0-2d30bbd6ca3295bcc82f90756098ae27)
返回结果也是DataFrame对象。转换后的字段和原表相同,记录变为两个,分别对应不同的分组,表中的数据是该字段不同组的均值。本例中使用了Numpy的均值函数,也可用自定义函数,或者使用lambda表达式定义处理方法,如下例中将每组中收入最高的记录作为变换后的值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_3.jpg?sign=1739520954-QA5Agxj4S9FZG5T5qFK4PH06sOktfUdX-0-264b9c58a735050013e55b20eb27da65)
3.3.3 转换
转换(Transform)是将数据表中的每个元素按不同组进行不同的转换处理,转换之后的行索引和列索引不变,只有内容改变。下例中将收入(INCOME)的实际值转换为INCOME减去该组的均值,用于表示其收入在所属组中是偏高还是偏低。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_87_4.jpg?sign=1739520954-ZQQI0d1XEUloMmNlAA0bJV704qRVHtzK-0-a9daea11b2a962359d1289a1a5fdd892)
聚合和转换都支持将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=1739520954-62nNpnpoPOkIrkTEBwhk4rYGIIwGEmXl-0-5a1ca3c00997400aa1e92fa3ac9f450d)
处理函数接收的参数是某一分组中的所有数据,返回布尔值。当布尔值为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=1739520954-83U8m4IF1tTAm9BI6dIJWI54HVsBub8b-0-8fe4b9929409486df8dac92fbb8f9b5b)
用apply实现转换功能:
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_88_4.jpg?sign=1739520954-ZD3fGT5mDLZz6x7sSoR2Bu2l6DheUGe4-0-9bfcf540832fdbcc1328c4cc27b84046)
用apply实现过滤功能与使用filter函数不同的是,当满足条件时,返回df;当不满足条件时,返回None,即在重组时忽略该返回值。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_89_1.jpg?sign=1739520954-Y8WE8Wl9tIGRrRMYLHie6DvWk2tDilFI-0-721c83eac74b3fa571b2e19cf99b7c0f)
除以上功能外,apply还提供更灵活的使用方式,比如返回符合条件组中的前N条。
![](https://epubservercos.yuewen.com/57F11A/16699150105739906/epubprivate/OEBPS/Images/38425_89_2.jpg?sign=1739520954-9Hh1v5BC0Akb7qb0NiImXduRhJ0Yxg5T-0-b53bc80f80cc2ef422cc25758dc38697)
Pandas对常用的聚合功能在底层做了优化,使apply函数的速度比自行分组计算之后再组合快得多,因此其是数据处理中不可或缺的工具。