例如(不确定是否最具代表性的例子):
N <- 1e6
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
这是我目前得到的:
d <- merge(d1,d2)
# 7.6 sec
library(plyr)
d <- join(d1,d2)
# 2.9 sec
library(data.table)
dt1 <- data.table(d1, key="x")
dt2 <- data.table(d2, key="x")
d <- data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
# 4.9 sec
library(sqldf)
sqldf()
sqldf("create index ix1 on d1(x)")
sqldf("create index ix2 on d2(x)")
d <- sqldf("select * from d1 inner join d2 on d1.x=d2.x")
sqldf()
# 17.4 sec
6条答案
按热度按时间ghhkc1vu1#
当第二个 Dataframe 中的每个键值对应于第一个 Dataframe 中的每个键值时,匹配方法有效。如果在第二 Dataframe 中存在重复,则匹配和合并方法不相同。Match当然更快,因为它没有做那么多。特别是它从不寻找重复的键。(代码后继续)
在问题中发布的sqldf代码中,可能看起来索引是在两个表上使用的,但事实上,它们被放置在sql select运行之前被覆盖的表上,这部分解释了为什么它如此缓慢。sqldf的思想是R会话中的 Dataframe 构成数据库,而不是sqlite中的表。因此,每当代码引用一个非限定的表名时,它将在R工作区中查找它--而不是在sqlite的主数据库中。因此,所显示的select语句将d1和d2从工作区读取到sqlite的主数据库中,从而清除了索引中的数据。因此,它执行没有索引的连接。如果你想使用sqlite主数据库中的d1和d2版本,你必须将它们称为main.d1和main.d2,而不是d1和d2。另外,如果你想让它尽可能快地运行,那么请注意,一个简单的连接不能同时使用两个表上的索引,所以你可以保存创建一个索引的时间。在下面的代码中,我们说明了这些要点。
值得注意的是,精确的计算可以对哪个包最快产生巨大的影响。例如,我们在下面进行合并和聚合。我们看到这两个结果几乎是相反的。在第一个例子中,从最快到最慢,我们得到:data.table、plyr、merge和sqldf,而在第二个例子中,sqldf、aggregate、data.table和plyr几乎与第一个相反。在第一个例子中,sqldf比data.table慢3倍,在第二个例子中,它比plyr快200倍,比data. table快100倍。下面我们展示了输入代码、合并的输出时间和聚合的输出时间。同样值得注意的是,sqldf基于数据库,因此可以处理比R更大的对象(如果使用sqldf的dbname参数),而其他方法仅限于在主存中处理。我们还用sqlite演示了sqldf,但它也支持H2和PostgreSQL数据库。
比较合并计算的两个基准调用的输出是:
比较聚合计算的基准调用的输出是:
cgyqldqp2#
Gabor的
data.table
结果中报告的132秒实际上是定时基函数colMeans
和cbind
(使用这些函数引起的内存分配和复制)。使用data.table
也有好的和坏的方法。请注意,我不太了解plyr,所以在依赖
plyr
计时之前,请与Hadley核对。还要注意的是,data.table
确实包括转换为data.table
和设置密钥的时间,以实现公平。此回答自2010年12月首次回答以来已更新。之前的基准测试结果如下所示。请查看此答案的修订历史,以了解发生了哪些变化。
czfnxgou3#
对于简单的任务(join两端的唯一值),我使用
match
:它比merge快得多(在我的机器上0.13s到3.37s)。
我的时间:
merge
:3.32splyr
:0.84smatch
:0.12s8gsdolmq4#
我想在混合中发布一个使用dplyr的基准测试会很有趣:(有很多东西在运行)
刚刚添加:
并使用数据表为dfur设置数据:
**更新:**我删除了data.tableBad和plyr,除了RStudio open(i7,16 GB RAM)之外什么都没有。
带数据。表1.9和带 Dataframe 的dplyr:
带数据表1.9和带数据表的dplyr:
为了保持一致性,这里是原始的所有和数据。表1.9和dplyr使用一个数据表:
我认为这个数据对于新的数据来说太小了。table和dplyr:)
更大的数据集:
在运行基准测试之前,需要大约10- 13 GB的内存来保存数据。
结果如下:
尝试了10亿,但炸毁了RAM。32 GB可以处理它没有问题。
[Edit(dotcomken,你能运行这段代码并粘贴你的基准测试结果吗?Thanks).
根据Arun的要求,您提供给我运行的输出:
很抱歉让你误会了,我熬夜了。
将dplyr与 Dataframe 一起使用似乎是处理摘要的效率较低的方法。这个方法是比较data.table和dplyr的确切功能以及它们的数据结构方法吗?我更倾向于将其分开,因为在我们group_by或创建data. table之前,大多数数据都需要清理。这可能是一个品味的问题,但我认为最重要的部分是如何有效地建模数据。
4dc9hkyq5#
通过使用merge函数及其可选参数:
Inner join:merge(df1,df2)将适用于这些示例,因为R会通过公共变量名自动连接框架,但您很可能希望指定merge(df1,df2,by =“CustomerId”)以确保仅匹配所需的字段。如果匹配的变量在不同的数据框中具有不同的名称,也可以使用by.x和by.y参数。
woobm2wo6#
一个老问题的最新答案:
collapse::join
为其他选项提供了一个(非常)快速的替代方案。我还在这里添加了一种使用on
进行data.table
连接的最新方法。使用nomatch = 0
执行内部连接。collapse::join
使用collapse::fmatch
作为主力。与
dplyr
、match
或merge
相比,collapse::join
绝对是快速连接的首选!数据和基准代码