使用 Pandas 分析亿行数据

声明,本文译自 pandas with hundreds of millions of rows。 部分译者补充了部分内容。

问题

我们希望获得国内航班平均延误最长的 5 个美国机场。

此处的国内航班指的是美国国内航班

dogs

数据

我们使用了来自 Harvard DataverseData Expo 2009: Airline on time data 数据集。该数据集包含从 1987 年 10 月到 2008 年 4 月美国境内所以商业航班降落和起飞的详细数据。 这大约有 1.2 亿条数据,分为 22 个 CSV 文件,每个 CSV 文件内包含 1 年的数据,以及 4 个我们不会使用的辅助 CSV 文件。 数据集解压后占用了大约 13 GB 硬盘空间。 原始数据集是经过压缩的,但解压缩部分不属于我们此次数据处理的任务。

原始数据集大概占用 1.3 GB 空间,使用 zip 压缩格式。

该数据集也在 《数据科学R语言实践》 此书中使用过。

环境

我使用以下硬件配置完成此项任务:

  • Intel® Core™ i7-8550U CPU @ 1.80GHz
  • 内存: LPDDR3 15820512 kB (16 Gb) 2133 MT/s, 无 swap
  • 硬盘: KXG50ZNV512G NVMe TOSHIBA 512GB(使用 ext4 分区格式且未进行加密)
  • 系统: Linux 5.19.9 (Arch 发行版, 仅运行 KDE Plasma 和单个 Konsole 会话, 占用 610 Mb 内存)

本文使用的软件配置如下:

幼稚方法

解决这一问题最简单的方法是直接使用 pandas 载入数据,代码如下:

import pandas

df = pandas.concat((pandas.read_csv(f'{
     year}.csv') for year in range(1987, 2009)))

不幸的是,该方案会引发 MemoryError (如果您使用 Jupyter 的话,此代码会导致内核重启)。 如果您的计算机存在大量内存,则不会出现此问题。 本文的其他部分将介绍一系列其他方式,使读者可以简单高效的完成此数据分析任务。

纯粹 Python 的方法

考虑到我们问题的特殊性,我们不需要将所有数据导入到内存中以计算每个机场的平均延迟。 我们可以读取数据行然后累加所需要的数据,即航班延迟和机场名称,然后丢弃此数据行。 当完成对所有数据行的读取后,我们获得了累加后的航班延迟,简单的与航班数量相除,我们就可以获得作为分析目标的平均值。

一个简单的实现如下:

import csv
import datetime
import heapq
import operator

USE_COLS = 'Origin', 'Year', 'Month', 'DayofMonth', 'CRSDepTime', 'DepTime'

airports = {
   }

for year in rage(1987, 2009):
    with open(f'../data/{
     year}.csv', errors='ignore') as f:
        reader = csv.reader(f)
        header = {
   name: position
                  for position, name
                  in enumerate(next(reader))
                  if name in USE_COLS}
        for row in reader:
            if row[header['CRSDepTime']] == 'NA' or row[header['DepTime']] == 'NA':
                continue

            year, month, day = (int(row[header['Year']]),
                                int(row[header['Month']]),
                                int(row[header['DayofMonth']]))

            try:
                scheduled_dep = datetime.datetime(year, month, day,
                                                  int(row[header['CRSDepTime']][:-2] or '0'),
                                                  int(row[header['CRSDepTime']][-2:]))
                actual_dep = datetime.datetime(year, month, day,
                                               int(row[header['DepTime']][:-2] or '0'),
                                               int(row[header['DepTime']][-2:]))
            except ValueError:
                continue

            delay = (actual_dep - scheduled_dep).total_seconds() / 3600.

            if delay < -2.:
                delay = 24. - delay

            
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值