读取单列 CSV 文件的更快方法
Posted
技术标签:
【中文标题】读取单列 CSV 文件的更快方法【英文标题】:Quicker way to read single column of CSV file 【发布时间】:2013-11-13 15:04:50 【问题描述】:我正在尝试尽快将CSV
文件的单个列读取到R
。我希望将标准方法减少 10 倍的将列放入 RAM 所需的时间。
我的动机是什么?我有两个文件;一个叫Main.csv
,它是300000行500列,一个叫Second.csv
,它是300000行5列。如果我system.time()
命令read.csv("Second.csv")
,则需要2.2 秒。现在,如果我使用以下两种方法中的任何一种来读取Main.csv
的第一列(这是Second.csv
的20%,因为它是1 列而不是5 列),它将花费40 多秒。 这与读取整个 600 MB 文件所需的时间相同——显然是不可接受的。
方法一
colClasses <- rep('NULL',500)
colClasses[1] <- NA
system.time(
read.csv("Main.csv",colClasses=colClasses)
) # 40+ seconds, unacceptable
方法二
read.table(pipe("cut -f1 Main.csv")) #40+ seconds, unacceptable
如何减少这个时间?我希望有一个R
解决方案。
【问题讨论】:
您可以将数据加载到数据库中并仅选择所需的列或使用 HDF5 文件而不是 csv。 @zero323 我需要一些可以是io
的东西:Python
、Java
、R
。
require(data.table); fread( "path/to/file/Main.csv" )
将立即提高您的速度。
我的old POC package 在这里可能会很有趣,它提供了一种以特殊二进制格式编写data.frame
的方法,以后可以用于一次仅读取几个变量。基本上它是save/readRDS
的包装器,并将列写入单独的文件等。更多详细信息:***.com/questions/4756989/…
你的 csv 文件真的是逗号分隔的吗?我认为scan(pipe("cut -f1 -d, Main.csv"))
可能值得一试。
【参考方案1】:
我建议
scan(pipe("cut -f1 -d, Main.csv"))
这与最初的提案 (read.table(pipe("cut -f1 Main.csv"))
) 在几个不同的方面有所不同:
cut
默认采用制表符分隔,所以需要指定d,
来指定逗号分隔
对于简单/非结构化数据读取,scan()
比 read.table
快得多。
根据 OP 的 cmets,这大约需要 4 秒而不是 40 多秒。
【讨论】:
看到你可以在读取文件之前用 Linux 命令行嵌套真是太神奇了。我什至可以在读取原始文件之前将我的 Python 清理程序放在管道命令中清理数据!我想知道是否可以有效地使用扫描从标准输入逐行读取表(每行是一行)? 绝对精彩。 @B.Mr.W.:恐怕你不会做得更好(我在其他地方看到了你的问题,但你的限制非常强:很难想象一种在 R 中逐行读取而无需大量开销的方法。)我认为scan
不会比readLines
快,但你为什么不试试看它是怎么回事?
@BenBolker 实际上您可以将fread
直接与系统命令一起使用,所以这...fread( "cut -f1 -d, Main.csv" )
可以更快吗?
也许吧,但scan()
确实没有太多开销(与read.table()
相比)【参考方案2】:
在blog 中有读取大型 CSV 文件的方法的速度比较。 fread 是最快的一个数量级。
如上面cmets中提到的,可以使用select参数来选择读取哪些列——所以:
fread("main.csv",sep = ",", select = c("f1") )
会起作用
【讨论】:
你能选择读入哪些行吗?即,按列的条件选择行?fread
等效于 SELECT col_1, col_2 FROM file WHERE col_3 > 30
。以上是关于读取单列 CSV 文件的更快方法的主要内容,如果未能解决你的问题,请参考以下文章