有效地连接长矩阵的大矩阵

时间:2017-09-01 12:39:41

标签: r rbindlist large-data

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

所以我决定用块读取文件,它工作(大约一个小时后),如果我信任{{1}中的环境选项卡,我会得到一个{G}的列表,需要2.5 Gb保存为RDS时,和1.2 Gb。

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

我想我可以通过rbindlist对列表项bind_rows使用rbindlist来解决这个问题,然后递归到我的最终列表时。这个n号码必须手动校准,而且这个过程非常难看(除了烦人的csv输入之外)。

我想到的另一个想法是找到一种方法从我加载的数据中提供SQLite数据库,然后从R查询它(我只会nn和{{ 1}}对数据的操作。)

我能做得比这更好吗?

我的数据仅由subsetmin组成,如果它有所不同。

2 个答案:

答案 0 :(得分:2)

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

require(bigmemory)

读取文件

您可以使用

big.matrix的形式阅读文件
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

提供了一些功能

子集column 1 is <= 5,和column 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

注意子集操作的结果是常规矩阵。您可以使用as.big.matrix()

将常规矩阵转换为big.matrix

最小值,最大值,平均值等

biganalyticsbig.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(...)

答案 1 :(得分:0)

在评论中提示后,我最终检查了这个solution,虽然我最终可能会最终接受@ 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的行为非常像data.frame,我认为有一些限制,但对于基本操作,它可以正常工作。

创建的数据库与csv源的大小大致相同,因此或多或少是RDS文件的4倍,但是具有很大的优势,不需要加载它在记忆中。

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

相关问题