R:快速访问大 CSV 文件的给定行

Posted

技术标签:

【中文标题】R:快速访问大 CSV 文件的给定行【英文标题】:R : Fast access to a given line of a big CSV file 【发布时间】:2018-03-28 08:34:49 【问题描述】:

我的数据源是 2GB 文件,由 3 列组成:key1、key2、result。 这些文件由超过 1000 万行组成。 我正在尝试在 Windows 系统上尽可能快地从 R 访问第 j 个文件的第 i 行。 Fread-ing 文件不是一个选项,因为它需要超过 2 分钟,这在这个用例中是不可能的。

我已经尝试了几种方法,但到目前为止都失败了:

方法 1: readlines、read.table 或 fread

readlines(file("myFile.csv", "r"),n=1, skip = M)

read.table("myFile.csv", skip=M, nrows=1)

fread("myFile.csv", skip=M, nrows=1)

这些方法的问题在于,当 M 趋于文件末尾时,访问时间很长。如果能找到类似的解决方案,我会非常感兴趣

方法2: fst包

正如评论/答案部分所建议的,由于From / To 参数,fst 包工作正常,但它需要在 FST 格式下复制 CSV,这在阅读时很难维护数千个 CSV 文件。 “基于csv”的解决方案会更好。

方法 3: SQLite DB

library(RSQLite)
library(data.table)
db <- dbConnect(SQLite(), "NEW_DB")
dbWriteTable(db, "chocs", fread("myFile.csv"), append = TRUE, row.names = FALSE)
dbGetQuery(db, "SELECT * FROM chocs WHERE V1 = 1 AND V2 = 1")

这种方法的问题是它创建 SQL DB 而 CSV 已经存在,并且查询不如方法 2 中提出的 FST 库那么快

有什么快速的方法吗?

【问题讨论】:

read.table() 来自基础 R。fread() 来自 data.table。 使用方法 3,在数据加载后类似于 dbGetQuery(db, "CREATE INDEX i1 ON chocs (V2, V1)") 并且在批量加载之前不创建主键索引(如 Panagiotis 所述) 主键是一个索引,对于插入的每一行都必须更新。批量加载数据时的一个常见技巧是禁用或删除索引,加载数据然后重建它们。 @NielsouAkbrg SQLite 可以直接使用.import 命令as shown here 导入CSV 文件。之后可以添加索引/主键 看看fstpackage.org 【参考方案1】:

fst 很好,正如我看到 cmets 中提到的@TimSalabim 一样,但是您必须先将其读取,然后将其写入 fst 文件。如果您需要在不同的会话中多次读取任意单行,那么我会说花 2 分钟将其作为具有fread 的数据表一次读取然后将其写为 fst 文件是合理的。

iris 的例子。

library(fst)
library(data.table)
DT <- data.table(iris)
write_fst(DT, "iris.fst")
x <- read_fst("iris.fst", from = 111, to = 111)
x
#  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
# 1          6.5         3.2          5.1           2 virginica

# exit your session, come back tomorrow
library(fst)
x <- read_fst("iris.fst", from = 99, to = 99)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
# 1          5.1         2.5            3         1.1 versicolor

当然,对你来说,你应该从

DT<- fread("myFile.csv")
write_fst(DT, "myFile.fst")
x <- read_fst("myFile.fst", from = 1e7, to = 1e7)

我现在在一台内存有限的极小机器上,所以我不打算创建一个 2GB 的对象并将其保存以进行测试,但是 iris 示例可以工作,并且一旦您花费了创建文件,您的行读取应该快得多。大概您使用的是一台支持 openMP 和 SSD 的不错的机器。

【讨论】:

我刚刚完成了@TimSalabim 提出的这个精确解决方案的测试,它正在创造奇迹。当 From = M 达到高位时,它的缩放比例非常好!很感动 @NielsouAkbrg 很高兴您找到ftshelpful。我认为它在易于使用和非常快速方面做得很好。如果您觉得这回答了您的问题,请将其标记为答案。如果您觉得它经过了充分的研究和很好的解释,请点赞! ***.com/help/someone-answers 我更新了您的帖子,但原生解决方案会更好。如果没有找到更好的,我会将其标记为 EOD 的答案。【参考方案2】:

data.table 包中的fread 怎么样?行选择可能如下所示:

dt[.(1,1), on = .(V1, V2)]

【讨论】:

是的,在这个时代,2 GB 并不大。正如这个答案所暗示的那样,我只是 fread 整个文件。 我确实阅读了整个文件,但耗时太长(大约 2 分钟)。

以上是关于R:快速访问大 CSV 文件的给定行的主要内容,如果未能解决你的问题,请参考以下文章

R 中的 hdf5 文件,用于通过 ID 进行快速随机访问

如何从 Perl 快速访问许多大型 CSV 文件中的数据?

在 R 中访问大型 csv:read.table.ffdf 变慢

如何有效且快速地将大型 (6 Gb) .csv 文件导入 R,而不会导致 R REPL 崩溃?

在powershell中快速比较两个大的csv(行和列)

如何将包含 200,00 行的巨大 CSV 文件导入 MySQL(异步且快速)?