pandas教程:GroupBy Mechanics 分组机制

文章目录

  • Chapter 10 Data Aggregation and Group Operations(数据汇总和组操作)
  • 10.1 GroupBy Mechanics(分组机制)
  • 1 Iterating Over Groups(对组进行迭代)
  • 2 Selecting a Column or Subset of Columns (选中一列,或列的子集)
  • 3 Grouping with Dicts and Series(用Dicts与Series进行分组)
  • 4 Grouping with Functions(用函数进行分组)
  • 5 Grouping by Index Levels (按索引层级来分组)

Chapter 10 Data Aggregation and Group Operations(数据汇总和组操作)

这一章的内容:

  • 把一个pandas对象(seriesDataFrame)按key分解为多个
  • 计算组的汇总统计值(group summary statistics),比如计数,平均值,标准差,或用户自己定义的函数
  • 应用组内的转换或其他一些操作,比如标准化,线性回归,排序,子集选择
  • 计算透视表和交叉列表
  • 进行分位数分析和其他一些统计组分析

10.1 GroupBy Mechanics(分组机制)

Hadley Wickham,是很多R语言有名库的作者,他描述group operation(组操作)为split-apply-combine(分割-应用-结合)。第一个阶段,存储于seriesDataFrame中的数据,根据不同的keys会被split(分割)为多个组。而且分割的操作是在一个特定的axis(轴)上。例如,DataFrame能按行(axis=0)或列(axis=1)来分组。之后,我们可以把函数apply(应用)在每一个组上,产生一个新的值。最后,所以函数产生的结果被combine(结合)为一个结果对象(result object)。下面是一个图示:

每一个用于分组的key能有很多形式,而且keys也不必都是一种类型:

  • 含有值的listarray的长度,与按axis分组后的长度是一样的
  • 值的名字指明的是DataFrame中的列名
  • 一个dictSeries,给出一个对应关系,用于对应按轴分组后的值与组的名字
  • 能在axis index(轴索引)上被调用的函数,或index上的labels(标签)

注意后面三种方法都是用于产生一个数组的快捷方式,而这个数组责备用来分割对象(split up the object)。不用担心这些很抽象,这一章会有很多例子来帮助我们理解这些方法。先从一个例子来开始吧,这里有一个用DataFrame表示的表格型数据集:

import numpy as np
import pandas as pd
df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],'key2' : ['one', 'two', 'one', 'two', 'one'], 'data1' : np.random.randn(5), 'data2' : np.random.randn(5)})
df
data1data2key1key2
01.3645330.633262aone
11.3533680.361008atwo
20.253311-1.107940bone
3-1.513444-1.038035btwo
4-0.9203172.037712aone

假设我们想要,通过使用key1作为labels,来计算data1列的平均值。有很多方法可以做到这点,一种是访问data1,并且使用列(a series)在key1上,调用groupby。(译者:其实就是按key1来进行分组,但只保留data1这一列):

grouped = df['data1'].groupby(df['key1'])
grouped
<pandas.core.groupby.SeriesGroupBy object at 0x111db3710>

这个grouped变量是一个GroupBy object(分组对象)。实际上现在还没有进行任何计算,除了调用group key(分组键)df['key1']时产生的一些中间数据。整个方法是这样的,这个GroupBy object(分组对象)已经有了我们想要的信息,现在需要的是对于每一个group(组)进行一些操作。例如,通过调用GroupBymean方法,我们可以计算每个组的平均值:

grouped.mean()
key1
a    0.599194
b   -0.630067
Name: data1, dtype: float64

之后我们会对于调用.mean()后究竟发生了什么进行更详细的解释。重要的是,我们通过group key(分组键)对数据(a series)进行了聚合,这产生了一个新的Series,而且这个series的索引是key1列中不同的值。

得到的结果中,index(索引)也有’key1’,因为我们使用了df['key1']

如果我们传入多个数组作为一个list,那么我们会得到不同的东西:

means = df['data1'].groupby([df['key1'], df['key2']]).mean()
means
key1  key2
a     one     0.222108two     1.353368
b     one     0.253311two    -1.513444
Name: data1, dtype: float64

这里我们用了两个key来分组,得到的结果series现在有一个多层级索引,这个多层索引是根据key1key2不同的值来构建的:

means.unstack()
key2onetwo
key1
a0.2221081.353368
b0.253311-1.513444

在上面的例子里,group key全都是series,即DataFrame中的一列,当然,group key只要长度正确,可以是任意的数组:

states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
years = np.array([2005, 2005, 2006, 2005, 2006])
df['data1'].groupby([states, years]).mean()
California  2005    1.3533682006    0.253311
Ohio        2005   -0.0744562006   -0.920317
Name: data1, dtype: float64
df['data1'].groupby([states, years])
<pandas.core.groupby.SeriesGroupBy object at 0x112530e48>
df['data1']
0    1.364533
1    1.353368
2    0.253311
3   -1.513444
4   -0.920317
Name: data1, dtype: float64
df
data1data2key1key2
01.3645330.633262aone
11.3533680.361008atwo
20.253311-1.107940bone
3-1.513444-1.038035btwo
4-0.9203172.037712aone

其中分组信息经常就在我们处理的DataFrame中,在这种情况下,我们可以传入列名(可以是字符串,数字,或其他python对象)作为group keys

df.groupby('key1').mean()
data1data2
key1
a0.5991941.010661
b-0.630067-1.072987
df.groupby(['key1', 'key2']).mean()
data1data2
key1key2
aone0.2221081.335487
two1.3533680.361008
bone0.253311-1.107940
two-1.513444-1.038035

我们注意到第一个例子里,df.groupby('key1').mean()的结果里并没有key2这一列。因为df['key2']这一列不是数值型数据,我们称这种列为nuisance column(有碍列),这种列不会出现在结果中。默认,所有的数值型列都会被汇总计算,但是出现有碍列的情况的话,就会过滤掉这种列。

一个很有用的GroupBy方法是size,会返回一个包含group size(组大小)的series

df.groupby(['key1', 'key2']).size()
key1  key2
a     one     2two     1
b     one     1two     1
dtype: int64

另外一点需要注意的是,如果作为group key的列中有缺失值的话,也不会出现在结果中。

1 Iterating Over Groups(对组进行迭代)

GroupBy对象支持迭代,能产生一个2-tuple(二元元组),包含组名和对应的数据块。考虑下面的情况:

for name, group in df.groupby('key1'):print(name)print(group)
adata1     data2 key1 key2
0  1.364533  0.633262    a  one
1  1.353368  0.361008    a  two
4 -0.920317  2.037712    a  one
bdata1     data2 key1 key2
2  0.253311 -1.107940    b  one
3 -1.513444 -1.038035    b  two

对于有多个key的情况,元组中的第一个元素会被作为另一个元组的key

for (k1, k2), group in df.groupby(['key1', 'key2']):print((k1, k2))print(group)
('a', 'one')data1     data2 key1 key2
0  1.364533  0.633262    a  one
4 -0.920317  2.037712    a  one
('a', 'two')data1     data2 key1 key2
1  1.353368  0.361008    a  two
('b', 'one')data1    data2 key1 key2
2  0.253311 -1.10794    b  one
('b', 'two')data1     data2 key1 key2
3 -1.513444 -1.038035    b  two

当然,也可以对数据的一部分进行各种操作。一个便利的用法是,用一个含有数据片段(data pieces)的dict来作为单行指令(one-liner)

pieces = dict(list(df.groupby('key1')))
pieces
{'a':       data1     data2 key1 key20  1.364533  0.633262    a  one1  1.353368  0.361008    a  two4 -0.920317  2.037712    a  one, 'b':       data1     data2 key1 key22  0.253311 -1.107940    b  one3 -1.513444 -1.038035    b  two}
pieces['b']
data1data2key1key2
20.253311-1.107940bone
3-1.513444-1.038035btwo

groupby默认作用于axis=0,但是我们可以指定任意的轴。例如,我们可以按dtype来对列进行分组:

df.dtypes
data1    float64
data2    float64
key1      object
key2      object
dtype: object
grouped = df.groupby(df.dtypes, axis=1)
for dtype, group in grouped:print(dtype)print(group)
float64data1     data2
0  1.364533  0.633262
1  1.353368  0.361008
2  0.253311 -1.107940
3 -1.513444 -1.038035
4 -0.920317  2.037712
objectkey1 key2
0    a  one
1    a  two
2    b  one
3    b  two
4    a  one

2 Selecting a Column or Subset of Columns (选中一列,或列的子集)

如果一个GroupBy对象是由DataFrame创建来的,那么通过列名或一个包含列名的数组来对GroupBy对象进行索引的话,就相当于对列取子集做聚合(column subsetting for aggregation)。这句话的意思是:

df.groupby('key1')['data1'] 
df.groupby('key1')[['data2']]

上面的代码其实就是下面的语法糖(Syntactic sugar):

df['data1'].groupby(df['key1']) 
df[['data2']].groupby(df['key1'])

语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程)创造的一个词语,它意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西。

尤其是对于一些很大的数据集,这种用法可以聚集一部分列。例如,在处理一个数据集的时候,想要只计算data2列的平均值,并将结果返还为一个DataFrame,我们可以这样写:

df
data1data2key1key2
01.3645330.633262aone
11.3533680.361008atwo
20.253311-1.107940bone
3-1.513444-1.038035btwo
4-0.9203172.037712aone
df.groupby(['key1', 'key2'])[['data2']].mean()
data2
key1key2
aone1.335487
two0.361008
bone-1.107940
two-1.038035

如果一个list或一个数组被传入,返回的对象是一个分组后的DataFrame,如果传入的只是单独一个列名,那么返回的是一个分组后的grouped

s_grouped = df.groupby(['key1', 'key2'])['data2']
s_grouped
<pandas.core.groupby.SeriesGroupBy object at 0x1125309e8>
s_grouped.mean()
key1  key2
a     one     1.335487two     0.361008
b     one    -1.107940two    -1.038035
Name: data2, dtype: float64

3 Grouping with Dicts and Series(用Dicts与Series进行分组)

分组信息可以不是数组的形式。考虑下面的例子:

people = pd.DataFrame(np.random.randn(5, 5),columns=['a', 'b', 'c', 'd', 'e'],index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
people.iloc[2:3, [1, 2]] = np.nan # Add a few NA values
people
abcde
Joe1.358054-0.1243780.159913-0.006129-1.116065
Steve0.926572-0.281652-0.586583-0.266538-0.216959
Wes0.277803NaNNaN0.820144-0.002076
Jim1.6232140.1094142.9676030.0756611.085864
Travis-0.5787501.2526050.7574120.352343-1.342396

假设我们有一个组,对应多个列,而且我们想要按组把这些列的和计算出来:

mapping = {'a': 'red', 'b': 'red', 'c': 'blue','d': 'blue', 'e': 'red', 'f': 'orange'}

现在,我们可以通过这个dict构建一个数组,然后传递给groupby,但其实我们可以直接传入dict(可以注意到key里有一个'f',这说明即使有,没有被用到的group key,也是ok的):

by_column = people.groupby(mapping, axis=1)
by_column.sum()
bluered
Joe0.1537840.117611
Steve-0.8531210.427961
Wes0.8201440.275727
Jim3.0432642.818492
Travis1.109754-0.668541

这种用法同样适用于series,这种情况可以看作是固定大小的映射(fixed-size mapping):

map_series = pd.Series(mapping)
map_series
a       red
b       red
c      blue
d      blue
e       red
f    orange
dtype: object
people.groupby(map_series, axis=1).count()
bluered
Joe23
Steve23
Wes12
Jim23
Travis23

4 Grouping with Functions(用函数进行分组)

比起用dictseries定义映射关系,使用python的函数是更通用的方法。任何一个作为group key的函数,在每一个index value(索引值)上都会被调用一次,函数计算的结果在返回的结果中会被用做group name。更具体一点,考虑前一个部分的DataFrame,用人的名字作为索引值。假设我们想要按照名字的长度来分组;同时我们要计算字符串的长度,使用len函数会变得非常简单:

people.groupby(len).sum() # len函数在每一个index(即名字)上被调用了
abcde
33.259071-0.0149643.1275160.889676-0.032277
50.926572-0.281652-0.586583-0.266538-0.216959
6-0.5787501.2526050.7574120.352343-1.342396

混合不同的函数、数组,字典或series都不成问题,因为所有对象都会被转换为数组:

key_list = ['one', 'one', 'one', 'two', 'two']
people.groupby([len, key_list]).min()
abcde
3one0.277803-0.1243780.159913-0.006129-1.116065
two1.6232140.1094142.9676030.0756611.085864
5one0.926572-0.281652-0.586583-0.266538-0.216959
6two-0.5787501.2526050.7574120.352343-1.342396

5 Grouping by Index Levels (按索引层级来分组)

最后关于多层级索引数据集(hierarchically indexed dataset),一个很方便的用时是在聚集(aggregate)的时候,使用轴索引的层级(One of the levels of an axis index)。看下面的例子:

columns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'], [1, 3, 5, 1, 3]], names=['cty', 'tenor'])
columns
MultiIndex(levels=[['JP', 'US'], [1, 3, 5]],labels=[[1, 1, 1, 0, 0], [0, 1, 2, 0, 1]],names=['cty', 'tenor'])
hier_df = pd.DataFrame(np.random.randn(4, 5), columns=columns)
hier_df
ctyUSJP
tenor13513
0-0.8980730.156686-0.1510110.4238810.336215
10.7363010.9015150.0816550.450248-0.031245
2-1.619125-1.0417750.1294221.222881-0.717410
30.998536-1.3734551.724266-2.0845290.535651

要想按层级分组,传入层级的数字或者名字,通过使用level关键字:

hier_df.groupby(level='cty', axis=1).count()
ctyJPUS
023
123
223
323

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/143776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小程序中如何设置门店信息

小程序是商家转型升级的利器&#xff0c;小程序中门店信息的准确性和完整性对于用户的体验和信任度都有很大的影响。下面具体介绍门店信息怎么在小程序中进行设置。 在小程序管理员后台->门店设置处&#xff0c;可以门店设置相关。主要分为2个模块&#xff0c;一个是门店级…

Linux-CentOS重要模块

软件包管理器&#xff1a;CentOS使用Yum&#xff08;Yellowdog Updater, Modified&#xff09;作为其包管理器。Yum提供了一种方便的方式来安装、更新和删除软件包&#xff0c;并自动解决依赖关系。 RPM&#xff1a;RPM&#xff08;RPM Package Manager&#xff09;是CentOS中…

CocosCreator3.8神秘面纱 CocosCreator 项目结构说明及编辑器的简单使用

我们通过Dashboard 创建一个2d项目&#xff0c;来演示CocosCreator 的项目结构。 等待创建完成后&#xff0c;会得到以下项目工程&#xff1a; 一、assets文件夹 assets文件夹&#xff1a;为资源目录&#xff0c;用来存储所有的本地资源&#xff0c;如各种图片&#xff0c;脚本…

posix定时器的使用

POSIX定时器是基于POSIX标准定义的一组函数&#xff0c;用于实现在Linux系统中创建和管理定时器。POSIX定时器提供了一种相对较高的精度&#xff0c;可用于实现毫秒级别的定时功能。 POSIX定时器的主要函数包括&#xff1a; timer_create()&#xff1a;用于创建一个定时器对象…

C++网络编程库编写自动爬虫程序

首先&#xff0c;我们需要使用 C 的网络编程库来编写这个爬虫程序。以下是一个简单的示例&#xff1a; #include <iostream> #include <string> #include <curl/curl.h> #include <openssl/ssl.h>const char* proxy_host "duoip"; const in…

LuatOS-SOC接口文档(air780E)--pack - 打包和解包格式串

pack.unpack( string, format, init) 解包字符串 参数 传入值类型 解释 string 需解包的字符串 string 格式化符号 ‘<’:设为小端编码 ‘>’:设为大端编码 ‘’:大小端遵循本地设置 ‘z’:空字符串 ‘p’:byte字符串 ‘P’:word字符串 ‘a’:size_t字符串 ‘A’:…

springmvc中针对一个controller方法配置两个url请求

记录一个小知识点。 某些应用场景》。。你可能需要不同的url请求得到相同的结果&#xff0c;那么你写两个方法总是不太好的&#xff0c;使用下面的方法可以解决这个问题。 RequestMapping(value { "/item/index.htm", "/product/index.htm" })public Mod…

k8s yaml文件含义

文章目录 1、YAML的文件格式和注意事项2、YAML各个字段含义 1、YAML的文件格式和注意事项 不支持制表符tab键缩进&#xff0c;需要使用空格缩进&#xff0c;使用缩进表示层级关系通常开头缩进2个空格&#xff0c;缩进的空格数不重要&#xff0c;只要相同层级的元素左对齐即可字…

【Python】基础(学习笔记)

一、Python介绍 1、Python优点 学习成本低 开源 适应⼈群⼴泛 应⽤领域⼴泛 2、Python解释器 Python解释器作用&#xff1a;运行Python文件 Python解释器分类 CPython&#xff1a;C语⾔开发的解释器[官⽅]&#xff0c;应⽤⼴泛的解释器。 IPython&#xff1a;基于CPyth…

为RabbitMQ配置SSL

1. 安装 OpenSSL 从 OpenSSL 的官方网站&#xff08;https://www.openssl.org/&#xff09;下载 OpenSSL 工具的 Windows 版本&#xff0c;并安装。 2. 创建 SSL 证书和私钥 执行以下命令以生成私钥文件&#xff08;.key&#xff09;和证书签名请求文件&#xff08;.csr&…

Spring中有哪几种方法获取HttpSession对象

Spring MVC 可以直接作为Controller的参数传入&#xff1a; RequestMapping(value "/test", method RequestMethod.POST, produces "application/json;charsetUTF-8")ResponseBodypublic Map test(HttpSession session, String otherParam) {//TODOre…

线性代数理解笔记

一.向量引入: 向量&#xff1a;只由大小和方向决定&#xff0c;不由位置决定。 二.向量加减法 向量的加法是首尾相连&#xff0c;减法是尾尾相连。 而向量v向量w为平行四边形主对角线。 向量v-向量w为平行四边形副对角线。 2.向量内积点乘&#xff08;内积&#xff09; 内积…

Java --- JVM之StringTable

目录 一、String的基本特性 二、String的内存分配 2.1、String内存分布图 三、字符串拼接操作 3.1、字符串拼接操作底层原理 3.2、拼接操作与append操作效率对比 四、intern()方法 4.1、intern()效率 五、StringTable的垃圾回收 一、String的基本特性 1、String字符…

MR外包团队:MR、XR混合现实技术应用于游戏、培训,心理咨询、教育成为一种创新的各行业MR、XR形式!

随着VR、AR、XR、MR混合现实等技术逐渐应用于游戏开发、心理咨询、培训、教育各个领域&#xff0c;为教育、培训、心理咨询等行业带来了全新的可能性。MR、XR游戏开发、心理咨询是利用虚拟现实技术模拟真实场景&#xff0c;让学生身临其境地参与学习和体验&#xff0c;从而提高…

为什么UI自动化难做?—— 关于Selenium UI自动化的思考

在快速迭代的产品、团队中&#xff0c;UI自动化通常是一件看似美好&#xff0c;实际“鸡肋”&#xff08;甚至绝大部分连鸡肋都算不上&#xff09;的工具。原因不外乎以下几点&#xff1a; 1 效果有限 通常只是听说过&#xff0c;就想去搞UI自动化的团队&#xff0c;心里都认…

SpringSecurity6从入门到上天系列第六篇:解决这个问题为什么在引入SpringSecurity之后所有的请求都需要先做登录认证才可以进行访问呢

文章目录 问题引入 1&#xff1a;问题阐述 2&#xff1a;问题分析 一&#xff1a;从SpringBoot的自动装配 1&#xff1a;SpringBootApplication介绍 2&#xff1a;自动装配的核心方法 3&#xff1a;核心方法的调用路径 4&#xff1a;SpringSecurity核心配置 5&#xf…

总结1057

考研倒计38天 极限冲刺day1 今日共计学习13h33m&#xff0c;为了能走出备考的低谷阶段&#xff0c;来一场与自我的较量。在尽可能保证效率的情况下&#xff0c;玩命干。考研这件事&#xff0c;从来不是因为看到了希望才去努力&#xff0c;而是玩命努力后才看到希望。

蒙HarmonyOS从零实现类微信app效果第二篇,我的+发现页面实现

本着不拖更的原则&#xff0c;今天上新了&#xff0c;今天实现了类微信app的发现页和我的页面。先看效果。 效果是不是看着还不错。其实这两个页面功能实现还是比较简单的&#xff0c;接下来还是老规矩&#xff0c;先进行页面的拆分和代码实现&#xff0c;然后进行相关我认为比…

ElementPlus el-switch开关页面初始化时,change事件自动触发

解决方案&#xff1a; //在el-switch外层包一个盒子 不使用el-switch自带的 change 事件 //盒子上面添加一个 click 点击事件&#xff0c;通过点击事件来改变el-switch的状态 <div click"switchChange"><el-switch v-model"value1" /> </d…

vue和react项目中实现 px 转 vm

vue和react项目中实现 px 转 vm vue中配置 1、下载插件 npm i postcss-px-to-viewport2、vue项目配置 const { defineConfig } require(vue/cli-service); const AutoImport require(unplugin-auto-import/webpack); const Components require(unplugin-vue-components/…