《Python Cookbook(第3版)中文版》——1.15 根据字段将记录分组

简介:

本节书摘来自异步社区《Python Cookbook(第3版)中文版》一书中的第1章,第1.15节,作者[美]David Beazley , Brian K.Jones,陈舸 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.15 根据字段将记录分组

1.15.1 问题

有一系列的字典或对象实例,我们想根据某个特定的字段(比如说日期)来分组迭代数据。

1.15.2 解决方案

itertools.groupby()函数在对数据进行分组时特别有用。为了说明其用途,假设有如下的字典列表:

rows = [
    {'address': '5412 N CLARK', 'date': '07/01/2012'},
    {'address': '5148 N CLARK', 'date': '07/04/2012'},
    {'address': '5800 E 58TH', 'date': '07/02/2012'},
    {'address': '2122 N CLARK', 'date': '07/03/2012'},
    {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
    {'address': '1060 W ADDISON', 'date': '07/02/2012'},
    {'address': '4801 N BROADWAY', 'date': '07/01/2012'},
    {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]

现在假设想根据日期以分组的方式迭代数据。要做到这些,首先以目标字段(在这个例子中是date)来对序列排序,然后再使用itertools.groupby()。

from operator import itemgetter
from itertools import groupby

# Sort by the desired field first
rows.sort(key=itemgetter('date'))

# Iterate in groups
for date, items in groupby(rows, key=itemgetter('date')):
    print(date)
    for i in items:
        print(' ', i)

这会产生如下的输出:

07/01/2012
     {'date': '07/01/2012', 'address': '5412 N CLARK'}
     {'date': '07/01/2012', 'address': '4801 N BROADWAY'}
07/02/2012
     {'date': '07/02/2012', 'address': '5800 E 58TH'}
     {'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'}
     {'date': '07/02/2012', 'address': '1060 W ADDISON'}
07/03/2012
     {'date': '07/03/2012', 'address': '2122 N CLARK'}
07/04/2012
     {'date': '07/04/2012', 'address': '5148 N CLARK'}
     {'date': '07/04/2012', 'address': '1039 W GRANVILLE'}

1.15.3 讨论

函数groupby()通过扫描序列找出拥有相同值(或是由参数key指定的函数所返回的值)的序列项,并将它们分组。groupby()创建了一个迭代器,而在每次迭代时都会返回一个值(value)和一个子迭代器(sub_iterator),这个子迭代器可以产生所有在该分组内具有该值的项。

在这里重要的是首先要根据感兴趣的字段对数据进行排序。因为groupby()只能检查连续的项,不首先排序的话,将无法按所想的方式来对记录分组。

如果只是简单地根据日期将数据分组到一起,放进一个大的数据结构中以允许进行随机访问,那么利用defaultdict()构建一个一键多值字典(multidict,见1.6节)可能会更好。例如:

from collections import defaultdict
rows_by_date = defaultdict(list)
for row in rows:
    rows_by_date[row['date']].append(row)

这使得我们可以方便地访问每个日期的记录,如下所示:

>>> for r in rows_by_date['07/01/2012']:
...      print(r)
...
{'date': '07/01/2012', 'address': '5412 N CLARK'}
{'date': '07/01/2012', 'address': '4801 N BROADWAY'}
>>>

对于后面这个例子,我们并不需要先对记录做排序。因此,如果不考虑内存方面的因素,这种方式会比先排序再用groupby()迭代要来的更快。

相关文章
|
5月前
|
数据挖掘 Python
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
【Python】已解决:Python pandas读取Excel表格某些数值字段结果为NaN问题
516 0
|
6月前
|
Python Windows
Python基础教程(第3版)中文版 第18章 程序打包 (笔记)
Python基础教程(第3版)中文版 第18章 程序打包 (笔记)
|
5月前
|
机器学习/深度学习 算法 数据挖掘
Python实现聚类(Kmeans)分析客户分组
Python实现聚类(Kmeans)分析客户分组
Python实现聚类(Kmeans)分析客户分组
|
6月前
|
SQL 安全 API
Python基础教程(第3版)中文版 第13章 数据库支持(笔记)
Python基础教程(第3版)中文版 第13章 数据库支持(笔记)
|
6月前
|
Python
Python基础教程(第3版)中文版 第20章 项目1: 自动添加标签(纯文本转HTML格式) (笔记2)
Python基础教程(第3版)中文版 第20章 项目1: 自动添加标签(纯文本转HTML格式) (笔记2)
|
6月前
|
Python
Python基础教程(第3版)中文版 第20章 项目1: 自动添加标签(纯文本转HTML格式) (笔记)
Python基础教程(第3版)中文版 第20章 项目1: 自动添加标签(纯文本转HTML格式) (笔记)
|
6月前
|
存储 设计模式 算法
Python基础教程(第3版)中文版 第19章 趣味编程 (笔记)
Python基础教程(第3版)中文版 第19章 趣味编程 (笔记)
|
6月前
|
Java C# C++
Python基础教程(第3版)中文版 第17章 扩展python (笔记)
Python基础教程(第3版)中文版 第17章 扩展python (笔记)
|
6月前
|
移动开发 测试技术 C语言
Python基础教程(第3版)中文版 第16章 测试基础(笔记)
Python基础教程(第3版)中文版 第16章 测试基础(笔记)
|
6月前
|
XML 数据格式 Python
Python基础教程(第3版)中文版 第15章 python和web(笔记)
Python基础教程(第3版)中文版 第15章 python和web(笔记)