0

我有一个 4 Gb 的 csv 文件要加载到我的 16 Gb 机器中,freadread.csv无法立即加载,它们会返回内存错误。

所以我决定逐块读取文件,它工作(大约一小时后),data.frames如果我信任环境选项卡,我会得到一个需要 2.5 Gb的列表RStudio,而保存为 RDS 时需要 1.2 Gb。

我现在遇到的问题是将所有内容连接回一个大的data.frame. 据我了解rbindlist是最有效的解决方案(或者是bind_rows?),但在我的情况下它仍然使用太多内存。

我想我可以通过rbindlist在列表项上使用nby来解决这个问题n,然后递归地直到我得到我的最终列表。不过,这个n数字必须手动校准,而且这个过程真的很难看(除了这个烦人的 csv 导入之外)。

我想到的另一个想法是找到一种方法来从我加载的数据中提供一个 SQLite 数据库,然后从 R 中查询它(我只会对数据执行subset,minmax操作)。

我能做得比这更好吗?

我的数据仅由integerand组成double,如果它有所作为。

4

2 回答 2

4

听起来bigmemory可能有足够的功能来解决您的问题

require(bigmemory)

读取文件

您可以使用big.matrixwith读取文件

read.big.matrix(filename, sep = ",", header = FALSE, col.names = NULL,
    row.names = NULL, has.row.names = FALSE, ignore.row.names = FALSE,
    type = NA, skip = 0, separated = FALSE, backingfile = NULL,
    backingpath = NULL, descriptorfile = NULL, binarydescriptor = FALSE,
    extraCols = NULL, shared = TRUE)

节省内存

即使是一个简单的例子iris,你也可以看到内存节省

x <- as.big.matrix(iris)
options(bigmemory.allow.dimnames=TRUE)
colnames(x) <- c("A", "B", "C", "D", "E")

object.size(x)
# 664 bytes

object.size(iris)
# 7088 bytes

子集

子集big.matrices是有限的,但提供了一些功能mwhich

子集 if column 1 is <= 5, ANDcolumn 2 <= 4

x[mwhich(x, 1:2, list(c(5), c(4)), list(c('le'), c('le')), 'AND'),]

#       A   B   C   D E
# 2   4.9 3.0 1.4 0.2 1
# 3   4.7 3.2 1.3 0.2 1
# 4   4.6 3.1 1.5 0.2 1
# 5   5.0 3.6 1.4 0.2 1
# etc

注意子集运算的结果是一个正则矩阵。您可以将常规矩阵转换为 big.matrixas.big.matrix()

最小值、最大值、平均值等

biganalytics提供更多功能big.matrices

require(biganalytics)

colmin(x, cols = 1:2, na.rm = FALSE)
#   A   B 
# 4.3 2.0

colmax(x, cols = 1:2, na.rm = FALSE)
#   A   B 
# 7.9 4.4 

输出

最后你可以big.matrix输出

write.big.matrix(...)
于 2017-09-01T13:59:27.627 回答
0

按照评论中的提示,我最终检查了这个解决方案,尽管我最终可能会接受@CPak 的解决方案(我会及时编辑这篇文章并提供最终信息)。

对于我的具体情况,我以这种方式使用它,首先创建数据库并用我的表提供它:

library(RSQLite)
library(dplyr)
# define dbpath (ending with ".SQLite" to be clean), my_table_name, csv_path
db <- dbConnect(SQLite(), dbname = dbpath) # will create databse if it doesn't exist, and a connection
dbWriteTable(conn=db, name=my_table_name, value=csv_path, row.names=FALSE, header=TRUE) # creates table in DB
dbDisconnect(db) 

然后访问它:

db    <- dbConnect(SQLite(), dbname= dbpath) # creates a connection to db
my_table <- tbl(db, my_table_name)

然后 my_table 的行为非常像 a data.frame,我认为有一些限制,但对于基本操作它工作得很好。

创建的数据库与源的大小大致相同csv,因此比文件多或多或少 4 倍RDS,但最大的优势是不需要将其加载到内存中。

编辑:这可能值得调查readr::read_csv_chunkedchunked::read_csv_chunkwise

于 2017-09-01T14:37:47.657 回答