查询一个 2000 万行的 CSV 文件:Data.table 与 Data Frame

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

正如我在几篇博文中提到的,我一直在探索 土地注册处的价格数据集 ,虽然我最初一直在使用 SparkR,但我很好奇使用普通 R 探索数据集会有多容易。

我想我应该先将数据加载到数据框中,然后使用 deployer 运行相同的查询。

我之前遇到过 Hadley Wickham 的 readr 库,但没有使用过它,因为我需要加载一个 2000 万行的 CSV 文件,这似乎是尝试它的最佳时机。

readr 的目标是提供一种快速友好的方式将表格数据读入 R。

让我们开始吧:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

所以将 CSV 文件处理成数据框花了 2 分钟多一点。让我们快速浏览一下它的内容:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

现在让我们查询数据框,看看哪个邮政编码的平均售价最高。在应用一些聚合函数之前,我们需要按“X4”列进行分组:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

如果我们想找到有史以来最昂贵的房产而不是邮政编码的平均价格怎么办?


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

有趣的是,一个比第一个要快得多,尽管看起来我们只做了稍微少一点的工作。

在这一点上,我向 Ashok 提到了我的实验,他建议我尝试使用 data.table 看看它是否表现得更好。我以前没有使用过它,但能够 相当快地启动和运行 它:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

所以我们已经在解析时间上增加了一分钟,这非常好。让我们试着找出平均价格最高的邮政编码:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

嗯,看来我们需要将“V2”列设为数字。让我们这样做:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

这比我们的数据框版本快得多——大约 5 秒而不是大约 2 分钟。我们已经丢失了总销售额和销售列数,但我认为这只是因为我的 data.table foo 很弱,如果我们愿意,我们可以保留它们。

但就执行时间而言,这是一个良好的开端。现在我们试试通过邮政编码查询最高销售价格:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

我们得到了与以前相同的结果,这次用了大约 4 秒而不是大约 35 秒。

如果我们将邮政编码列设置为键,我们实际上可以做得更好:


 > library(readr)

> system.time(read_csv("pp-complete.csv", col_names = FALSE)) user system elapsed 127.367 21.957 159.963

> df = read_csv("pp-complete.csv", col_names = FALSE)

这就是我的实验所得到的。如果还有什么我可以做的来使这两个版本更快,请在评论中告诉我。

哦,关于我们可以从查询中学到什么的一些评论......骑士桥是一个非常昂贵的居住区!