在R中快速读取非常大的表格作为数据框
我有非常大的表(3000万行),我想在R中加载一个数据read.table()
有很多方便的功能,但是看起来好像有很多逻辑在执行时会减慢事情下降。 就我而言,我假设我提前知道列的类型,该表不包含任何列标题或行名称,并且没有任何我必须担心的病态字符。
我知道使用scan()
作为列表在表中读取可能非常快,例如:
datalist <- scan('myfile',sep='t',list(url='',popularity=0,mintime=0,maxtime=0)))
但是,我的一些尝试将其转换为数据帧似乎将上述性能降低了6倍:
df <- as.data.frame(scan('myfile',sep='t',list(url='',popularity=0,mintime=0,maxtime=0))))
有没有更好的方法来做到这一点? 或者可能完全不同的方法来解决这个问题?
数年后的更新
这个答案是旧的,R已经开始了。 调整read.table
以更快运行会带来宝贵的好处。 您的选择是:
在data.table
使用fread
将csv /制表符分隔文件中的数据直接导入R.请参阅mnel的答案。
使用read_table
在readr
(从2015年4月在CRAN)。 这很像上面的fread
。 链接中的readme解释了两个函数之间的区别( readr
目前声称比data.table::fread
慢data.table::fread
)。
read.csv.raw
从iotools
提供了快速读取CSV文件第三个选项。
试图在数据库中存储尽可能多的数据而不是平面文件。 (除了作为一个更好的永久存储介质,数据被传递到和来自R以二进制格式,这是更快。) read.csv.sql
在sqldf
包,如在JD龙的回答那样,进口数据到临时SQLite数据库,然后将其读入R.另请参阅: RODBC
软件包,反向取决于DBI
软件包页的部分。 MonetDB.R
为您提供了一种假装为数据框的数据类型,但实际上是MonetDB,提高了性能。 用monetdb.read.csv
函数导入数据。 dplyr
允许您直接处理存储在多种类型的数据库中的数据。
以二进制格式存储数据对于提高性能也很有用。 使用saveRDS
/ readRDS
(见下文),该h5
或rhdf5
包HDF5格式,或write_fst
/ read_fst
从fst
包。
原来的答案
无论使用read.table还是scan,都有几件简单的事情可以尝试。
设置nrows
=数据中的记录数( scan
nmax
)。
确保comment.char=""
关闭评论的解释。
在read.table
使用colClasses
显式定义每个列的类。
设置multi.line=FALSE
也可以提高扫描的性能。
如果这些东西都不起作用,那么使用其中一个分析包来确定哪些线路正在放慢速度。 也许你可以根据结果编写一个read.table
的简化版本。
另一种方法是在将数据读入R之前过滤数据。
或者,如果问题是您必须定期读取它,则使用这些方法一次读取数据,然后使用save
saveRDS
将数据帧保存为二进制blob,然后下次load
读取速度更快readRDS
。
这是一个利用data.table
1.8.7中的fread
的例子
这些例子来自于帮助页fread
,对我的Windows XP的Core 2 Duo E8400的时机。
library(data.table)
# Demo speedup
n=1e6
DT = data.table( a=sample(1:1000,n,replace=TRUE),
b=sample(1:1000,n,replace=TRUE),
c=rnorm(n),
d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
e=rnorm(n),
f=sample(1:1000,n,replace=TRUE) )
DT[2,b:=NA_integer_]
DT[4,c:=NA_real_]
DT[3,d:=NA_character_]
DT[5,d:=""]
DT[2,e:=+Inf]
DT[3,e:=-Inf]
标准的read.table
write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)
cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"n")
## File size (MB): 51
system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))
## user system elapsed
## 24.71 0.15 25.42
# second run will be faster
system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))
## user system elapsed
## 17.85 0.07 17.98
优化的read.table
system.time(DF2 <- read.table("test.csv",header=TRUE,sep=",",quote="",
stringsAsFactors=FALSE,comment.char="",nrows=n,
colClasses=c("integer","integer","numeric",
"character","numeric","integer")))
## user system elapsed
## 10.20 0.03 10.32
FREAD
require(data.table)
system.time(DT <- fread("test.csv"))
## user system elapsed
## 3.12 0.01 3.22
sqldf
require(sqldf)
system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))
## user system elapsed
## 12.49 0.09 12.69
# sqldf as on SO
f <- file("test.csv")
system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))
## user system elapsed
## 10.21 0.47 10.73
ff / ffdf
require(ff)
system.time(FFDF <- read.csv.ffdf(file="test.csv",nrows=n))
## user system elapsed
## 10.85 0.10 10.99
综上所述:
## user system elapsed Method
## 24.71 0.15 25.42 read.csv (first time)
## 17.85 0.07 17.98 read.csv (second time)
## 10.20 0.03 10.32 Optimized read.table
## 3.12 0.01 3.22 fread
## 12.49 0.09 12.69 sqldf
## 10.21 0.47 10.73 sqldf on SO
## 10.85 0.10 10.99 ffdf
我最初没有看到这个问题,并在几天后问了一个类似的问题。 我将把我以前的问题解决,但我想我会在这里添加一个答案来解释我如何使用sqldf()
来执行此操作。
关于将2GB或更多文本数据导入到R数据框的最佳方法,我们已经讨论过很少。 昨天我写了一篇关于使用sqldf()
将数据作为暂存区导入SQLite的博客文章,然后将它从SQLite中吸收到R中。这对我来说非常有用。 我能够在<5分钟内获得2GB(3列,40mm行)的数据。 相比之下, read.csv
命令整夜运行并且从未完成。
这是我的测试代码:
设置测试数据:
bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
write.csv(bigdf, 'bigdf.csv', quote = F)
在运行以下导入例程之前,我重新启动了R:
library(sqldf)
f <- file("bigdf.csv")
system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))
我让下面一行运行整夜,但它从未完成:
system.time(big.df <- read.csv('bigdf.csv'))
链接地址: http://www.djcxy.com/p/30825.html
上一篇: Quickly reading very large tables as dataframes in R
下一篇: R inconsistency: why add=T sometimes works and sometimes not in the plot() function?