更高效的大数据框合并替代方案 R

30

我正在寻找一种高效的(在计算机资源和学习/实现方面都高效)方法来合并两个较大的数据框(大小> 1百万 / 300 KB RData文件)。

基于R的"merge"和plyr中的"join"似乎会有效地使用所有内存,导致系统崩溃。

示例:
加载测试数据框并尝试执行以下操作:

test.merged<-merge(test, test)
或者
test.merged<-join(test, test, type="all")  
    -

以下文章提供了一个合并和替代列表:
如何在R中连接(合并)数据框(inner、outer、left、right)?

以下允许对象大小检查:
https://heuristically.wordpress.com/2010/01/04/r-memory-usage-statistics-variable/

anonym产生的数据。


8
SQL.df 还是 data.table?SQL.df 和 data.table 都是处理数据的工具,但它们具有不同的优缺点和用途。要根据特定的情况选择使用哪种工具。 - Ari B. Friedman
在筛选了以下的好回复后,我找到了这个链接:https://dev59.com/XW855IYBdhLWcg3weUMQ (虽然问题并不是关于大型数据框,而只是关于节省毫秒的问题,但它得到了与以下回复类似的解答)。 - Etienne Low-Décarie
3个回答

27

下面是data.table和data.frame方法的一些时间对比。
使用data.table更快。关于内存方面,我可以非正式地报告两种方法在RAM使用方面非常相似(在20%以内)。

library(data.table)

set.seed(1234)
n = 1e6

data_frame_1 = data.frame(id=paste("id_", 1:n, sep=""),
                          factor1=sample(c("A", "B", "C"), n, replace=TRUE))
data_frame_2 = data.frame(id=sample(data_frame_1$id),
                          value1=rnorm(n))

data_table_1 = data.table(data_frame_1, key="id")
data_table_2 = data.table(data_frame_2, key="id")

system.time(df.merged <- merge(data_frame_1, data_frame_2))
#   user  system elapsed 
# 17.983   0.189  18.063 


system.time(dt.merged <- merge(data_table_1, data_table_2))
#   user  system elapsed 
#  0.729   0.099   0.821 

22
这里是必不可少的`data.table`示例:
library(data.table)

## Fix up your example data.frame so that the columns aren't all factors
## (not necessary, but shows that data.table can now use numeric columns as keys)
cols <- c(1:5, 7:10)
test[cols] <- lapply(cols, FUN=function(X) as.numeric(as.character(test[[X]])))
test[11] <- as.logical(test[[11]])

## Create two data.tables with which to demonstrate a data.table merge
dt <- data.table(test, key=names(test))
dt2 <- copy(dt)
## Add to each one a unique non-keyed column
dt$X <- seq_len(nrow(dt))
dt2$Y <- rev(seq_len(nrow(dt)))

## Merge them based on the keyed columns (in both cases, all but the last) to ...
## (1) create a new data.table
dt3 <- dt[dt2]
## (2) or (poss. minimizing memory usage), just add column Y from dt2 to dt
dt[dt2,Y:=Y]

谢谢你的绝佳答案。我想如果你想要保持原始顺序,可以添加一个1:grow(df)列并将其用作键的第一个元素? - Etienne Low-Décarie
@EtienneLow-Décarie -- 这是一个好问题。我认为你确实想要添加这样一列,但不要将其作为键的元素。这样你就可以在任何时候使用它来重新排序数据。(它不应该成为键的一部分,因为它只是一个顺序标记,而不是在不同数据集中具有相同含义的变量/组标识符)。 - Josh O'Brien
3
data.table是否代表不再需要apply和plyr函数?相当令人印象深刻! - Etienne Low-Décarie

0

你必须在R中进行合并吗?如果不是,可以使用简单的文件连接将基础数据文件合并,然后将它们加载到R中。(我意识到这可能不适用于您的情况--但如果适用,它可以为您节省很多麻烦。)


2
必须在R中实时完成,因为它是优化例程中的一步,写入磁盘可能会成为瓶颈。谢谢。 - Etienne Low-Décarie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接