笔记:《利用Python进行数据分析》之数据聚合

2024-09-01 19:44

本文主要是介绍笔记:《利用Python进行数据分析》之数据聚合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

观前提示:这节内容不多,但难度较大,尤其是要能熟练运用时很不容易的

数据聚合

聚合指的是任何能够从数组产生标量值的数据转换过程。之前的例子已经用过一些,比如mean、count、min以及sum等。你可能想知道在GroupBy对象上调用mean()时究竟发生了什么。许多常见的聚合运算(如表10-1所示)都有进行优化。然而,除了这些方法,你还可以使用其它的。

表10-1 经过优化的groupby方法

你可以使用自己发明的聚合运算,还可以调用分组对象上已经定义好的任何方法。例如,quantile可以计算Series或DataFrame列的样本分位数。

虽然quantile并没有明确地实现于GroupBy,但它是一个Series方法,所以这里是能用的。实际上,GroupBy会高效地对Series进行切片,然后对各片调用piece.quantile(0.9),最后将这些结果组装成最终结果:

In [51]: df
Out[51]: data1     data2 key1 key2
0 -0.204708  1.393406    a  one
1  0.478943  0.092908    a  two
2 -0.519439  0.281746    b  one
3 -0.555730  0.769023    b  two
4  1.965781  1.246435    a  one
In [52]: grouped = df.groupby('key1')
In [53]: grouped['data1'].quantile(0.9)
Out[53]: 
key1
a    1.668413
b   -0.523068
Name: data1, dtype: float64

如果要使用你自己的聚合函数,只需将其传入aggregate或agg方法即可:

In [54]: def peak_to_peak(arr):....:     return arr.max() - arr.min()
In [55]: grouped.agg(peak_to_peak)
Out[55]: data1     data2
key1                    
a     2.170488  1.300498
b     0.036292  0.487276

你可能注意到注意,有些方法(如describe)也是可以用在这里的,即使严格来讲,它们并非聚合运算:

In [56]: grouped.describe()
Out[56]: data1                                                              \count      mean       std       min       25%       50%       75%   
key1                                                                     
a      3.0  0.746672  1.109736 -0.204708  0.137118  0.478943  1.222362   
b      2.0 -0.537585  0.025662 -0.555730 -0.546657 -0.537585 -0.528512   data2                                                    \
max count      mean       std       min       25%       50%   
key1                                                                     
a     1.965781   3.0  0.910916  0.712217  0.092908  0.669671  1.246435   
b    -0.519439   2.0  0.525384  0.344556  0.281746  0.403565  0.525384   75%       max  
key1                      
a     1.319920  1.393406  
b     0.647203  0.769023

自定义聚合函数要比表10-1中那些经过优化的函数慢得多。这是因为在构造中间分组数据块时存在非常大的开销(函数调用、数据重排等)。

面向列的多函数应用

回到前面小费的例子。使用read_csv导入数据之后,我们添加了一个小费百分比的列tip_pct:

In [57]: tips = pd.read_csv('examples/tips.csv')
# Add tip percentage of total bill
In [58]: tips['tip_pct'] = tips['tip'] / tips['total_bill']
In [59]: tips[:6]
Out[59]: total_bill   tip smoker  day    time  size   tip_pct
0       16.99  1.01     No  Sun  Dinner     2  0.059447
1       10.34  1.66     No  Sun  Dinner     3  0.160542
2       21.01  3.50     No  Sun  Dinner     3  0.166587
3       23.68  3.31     No  Sun  Dinner     2  0.139780
4       24.59  3.61     No  Sun  Dinner     4  0.146808
5       25.29  4.71     No  Sun  Dinner     4  0.186240

你已经看到,对Series或DataFrame列的聚合运算其实就是使用aggregate(使用自定义函数)或调用诸如mean、std之类的方法。然而,你可能希望对不同的列使用不同的聚合函数,或一次应用多个函数。其实这也好办,我将通过一些示例来进行讲解。首先,我根据天和smoker对tips进行分组:

In [60]: grouped = tips.groupby(['day', 'smoker'])In [61]: grouped_pct = grouped['tip_pct']
In [62]: grouped_pct.agg('mean')
Out[62]: 
day   smoker
Fri   No        0.151650Yes       0.174783
Sat   No        0.158048Yes       0.147906
Sun   No        0.160113Yes       0.187250
Thur  No        0.160298Yes       0.163863
Name: tip_pct, dtype: float64

如果传入一组函数或函数名,得到的DataFrame的列就会以相应的函数命名:

In [63]: grouped_pct.agg(['mean', 'std', peak_to_peak])
Out[63]: mean       std  peak_to_peak
day  smoker                                  
Fri  No      0.151650  0.028123      0.067349Yes     0.174783  0.051293      0.159925
Sat  No      0.158048  0.039767      0.235193Yes     0.147906  0.061375      0.290095
Sun  No      0.160113  0.042347      0.193226Yes     0.187250  0.154134      0.644685
Thur No      0.160298  0.038774      0.193350Yes     0.163863  0.039389      0.151240

这里,我们传递了一组聚合函数进行聚合,独立对数据分组进行评估。

你并非一定要接受GroupBy自动给出的那些列名,特别是lambda函数,它们的名称是’‘,这样的辨识度就很低了(通过函数的name属性看看就知道了)。因此,如果传入的是一个由(name,function)元组组成的列表,则各元组的第一个元素就会被用作DataFrame的列名(可以将这种二元元组列表看做一个有序映射):

In [64]: grouped_pct.agg([('foo', 'mean'), ('bar', np.std)])
Out[64]: foo       bar
day  smoker                    
Fri  No      0.151650  0.028123Yes     0.174783  0.051293
Sat  No      0.158048  0.039767Yes     0.147906  0.061375
Sun  No      0.160113  0.042347Yes     0.187250  0.154134
Thur No      0.160298  0.038774Yes     0.163863  0.039389

对于DataFrame,你还有更多选择,你可以定义一组应用于全部列的一组函数,或不同的列应用不同的函数。假设我们想要对tip_pct和total_bill列计算三个统计信息:

In [65]: functions = ['count', 'mean', 'max']
In [66]: result = grouped['tip_pct', 'total_bill'].agg(functions)
In [67]: result
Out[67]: tip_pct                     total_bill                  count      mean       max      count       mean    max
day  smoker                                                         
Fri  No           4  0.151650  0.187735          4  18.420000  22.75Yes         15  0.174783  0.263480         15  16.813333  40.17
Sat  No          45  0.158048  0.291990         45  19.661778  48.33Yes         42  0.147906  0.325733         42  21.276667  50.81
Sun  No          57  0.160113  0.252672         57  20.506667  48.17Yes         19  0.187250  0.710345         19  24.120000  45.35
Thur No          45  0.160298  0.266312         45  17.113111  41.19Yes         17  0.163863  0.241255         17  19.190588  43.11

如你所见,结果DataFrame拥有层次化的列,这相当于分别对各列进行聚合,然后用concat将结果组装到一起,使用列名用作keys参数:

In [68]: result['tip_pct']
Out[68]: count      mean       max
day  smoker                           
Fri  No          4  0.151650  0.187735Yes        15  0.174783  0.263480
Sat  No         45  0.158048  0.291990Yes        42  0.147906  0.325733
Sun  No         57  0.160113  0.252672Yes        19  0.187250  0.710345
Thur No         45  0.160298  0.266312Yes        17  0.163863  0.241255

跟前面一样,这里也可以传入带有自定义名称的一组元组:

In [69]: ftuples = [('Durchschnitt', 'mean'),('Abweichung', np.var)]
In [70]: grouped['tip_pct', 'total_bill'].agg(ftuples)
Out[70]: tip_pct              total_bill            Durchschnitt Abweichung Durchschnitt  Abweichung
day  smoker                                                 
Fri  No         0.151650   0.000791    18.420000   25.596333Yes        0.174783   0.002631    16.813333   82.562438
Sat  No         0.158048   0.001581    19.661778   79.908965Yes        0.147906   0.003767    21.276667  101.387535
Sun  No         0.160113   0.001793    20.506667   66.099980Yes        0.187250   0.023757    24.120000  109.046044
Thur No         0.160298   0.001503    17.113111   59.625081Yes        0.163863   0.001551    19.190588   69.808518

现在,假设你想要对一个列或不同的列应用不同的函数。具体的办法是向agg传入一个从列名映射到函数的字典:

In [71]: grouped.agg({'tip' : np.max, 'size' : 'sum'})
Out[71]: tip  size
day  smoker             
Fri  No       3.50     9Yes      4.73    31
Sat  No       9.00   115Yes     10.00   104
Sun  No       6.00   167Yes      6.50    49
Thur No       6.70   112Yes      5.00    40
In [72]: grouped.agg({'tip_pct' : ['min', 'max', 'mean', 'std'],....:              'size' : 'sum'})
Out[72]: tip_pct                               sizemin       max      mean       std  sum
day  smoker                                             
Fri  No      0.120385  0.187735  0.151650  0.028123    9Yes     0.103555  0.263480  0.174783  0.051293   31
Sat  No      0.056797  0.291990  0.158048  0.039767  115Yes     0.035638  0.325733  0.147906  0.061375  104
Sun  No      0.059447  0.252672  0.160113  0.042347  167Yes     0.065660  0.710345  0.187250  0.154134   49
Thur No      0.072961  0.266312  0.160298  0.038774  112Yes     0.090014  0.241255  0.163863  0.039389   40

只有将多个函数应用到至少一列时,DataFrame才会拥有层次化的列。

以“没有行索引”的形式返回聚合数据

到目前为止,所有示例中的聚合数据都有由唯一的分组键组成的索引(可能还是层次化的)。由于并不总是需要如此,所以你可以向groupby传入as_index=False以禁用该功能:

In [73]: tips.groupby(['day', 'smoker'], as_index=False).mean()
Out[73]: day smoker  total_bill       tip      size   tip_pct
0   Fri     No   18.420000  2.812500  2.250000  0.151650
1   Fri    Yes   16.813333  2.714000  2.066667  0.174783
2   Sat     No   19.661778  3.102889  2.555556  0.158048
3   Sat    Yes   21.276667  2.875476  2.476190  0.147906
4   Sun     No   20.506667  3.167895  2.929825  0.160113
5   Sun    Yes   24.120000  3.516842  2.578947  0.187250
6  Thur     No   17.113111  2.673778  2.488889  0.160298
7  Thur    Yes   19.190588  3.030000  2.352941  0.163863

小结

数据聚合是数据分析中的一个重要概念,它涉及将一组数据转换成单个数值的过程。在Python的Pandas库中,数据聚合通常通过`GroupBy`对象来实现,该对象允许对数据进行分组,并对每个分组应用聚合函数。

以下是一些关键点的总结:

1. 常见聚合函数:如`mean`、`count`、`min`、`max`和`sum`等,它们可以直接应用于`GroupBy`对象。

2. 自定义聚合函数:用户可以定义自己的聚合函数,如`peak_to_peak`,然后通过`aggregate`或`agg`方法应用到`GroupBy`对象上。

3. 分位数计算:虽然`quantile`不是直接实现在`GroupBy`上,但它是`Series`的方法,可以通过`GroupBy`高效地对数据切片并应用。

4. 多函数聚合:可以对不同的列使用不同的聚合函数,或者一次应用多个函数。例如,使用`agg`方法传入一个函数列表或字典,对不同的列进行不同的聚合操作。

5. 列名自定义:在聚合时,可以通过传递`(name, function)`元组列表来自定义结果DataFrame的列名。

6. DataFrame的聚合:可以对DataFrame的不同列应用不同的函数,或者对所有列应用同一组函数。

7. 无索引的聚合结果:通过设置`as_index=False`,可以返回没有行索引的聚合数据,使得结果更易于理解和操作。

8. 描述性统计:方法如`describe`可以提供数据的描述性统计信息,虽然它们不是聚合运算,但可以用于`GroupBy`对象。

通过这些方法,Pandas提供了强大的工具来对数据进行分组和聚合,使得数据分析更加灵活和高效。

这篇关于笔记:《利用Python进行数据分析》之数据聚合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1127873

相关文章

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步