例如(不确定是否是最具代表性的例子):

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

推荐答案

当第二个数据帧中的每个键值对应于第一个数据帧中的每个键值时,匹配方法就会起作用.如果第二个数据帧中存在重复项,则匹配和合并方法不同.当然,Match的速度更快,因为它做的不多.尤其是,它从不寻找重复的密钥.(代码后续)

DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
    b a c
  1 1 1 a
  2 2 1 b
  3 3 2 c
  4 3 2 d
  5 4 2 e
DF1$c = DF2$c[match(DF1$b, DF2$b)]
DF1$c
[1] a b c e
Levels: a b c d e

> DF1
  a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e

在问题中发布的sqldf代码中,似乎在这两个表上使用了索引,但实际上,它们被放在了sql select运行之前被覆盖的表上,这在一定程度上解释了其速度如此之慢的原因.sqldf的思想是,R会话中的数据帧构成数据库,而不是sqlite中的表.因此,每次代码引用非限定表名时,它都会在R工作区中查找它,而不是在sqlite的主数据库中.因此,所显示的select语句将d1和d2工作区读取到sqlite的主数据库中,并用索引替换其中的数据库.因此,它执行一个没有索引的连接.如果您想使用sqlite主数据库中的d1和d2版本,您必须将它们称为main.d1和main.d2,而非d1和d2.此外,如果您试图让它尽可能快地运行,那么请注意,简单联接不能同时使用两个表上的索引,因此可以节省创建其中一个索引的时间.在下面的代码中,我们将说明这些要点.

值得注意的是,精确的计算可以对哪个包的速度最快产生巨大的影响.例如,我们在下面进行合并和聚合.我们发现,这两种情况的结果几乎相反.在第一个例子中,我们从最快到最慢得到:数据.table、plyr、merge和sqldf,而在第二个示例中,sqldf、aggregate和data.表和plyr——几乎与第一个相反.在第一个示例中,sqldf比数据慢3倍.表和第二个表比plyr快200倍,比数据快100倍.桌子下面我们展示了输入代码、合并的输出计时和聚合的输出计时.值得注意的是,sqldf基于数据库,因此可以处理比R更大的对象(如果使用sqldf的dbname参数),而其他方法仅限于在主存中处理.我们还用sqlite演示了sqldf,但它也支持H2和PostgreSQL数据库.

library(plyr)
library(data.table)
library(sqldf)

set.seed(123)
N <- 1e5
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))

g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(d1, g1, g2)

library(rbenchmark)

benchmark(replications = 1, order = "elapsed",
   merge = merge(d1, d2),
   plyr = join(d1, d2),
   data.table = { 
      dt1 <- data.table(d1, key = "x")
      dt2 <- data.table(d2, key = "x")
      data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
      },
   sqldf = sqldf(c("create index ix1 on d1(x)",
      "select * from main.d1 join d2 using(x)"))
)

set.seed(123)
N <- 1e5
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)

benchmark(replications = 1, order = "elapsed",
   aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean), 
   data.table = {
      dt <- data.table(d, key = "g1,g2")
      dt[, colMeans(cbind(x, y)), by = "g1,g2"]
   },
   plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
   sqldf = sqldf(c("create index ix on d(g1, g2)",
      "select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)

比较合并计算的两个基准调用的输出为:

Joining by: x
        test replications elapsed relative user.self sys.self user.child sys.child
3 data.table            1    0.34 1.000000      0.31     0.01         NA        NA
2       plyr            1    0.44 1.294118      0.39     0.02         NA        NA
1      merge            1    1.17 3.441176      1.10     0.04         NA        NA
4      sqldf            1    3.34 9.823529      3.24     0.04         NA        NA

比较合计计算的基准测试调用的输出为:

        test replications elapsed  relative user.self sys.self user.child sys.child
4      sqldf            1    2.81  1.000000      2.73     0.02         NA        NA
1  aggregate            1   14.89  5.298932     14.89     0.00         NA        NA
2 data.table            1  132.46 47.138790    131.70     0.08         NA        NA
3       plyr            1  212.69 75.690391    211.57     0.56         NA        NA

R相关问答推荐

r带有参考年的两年移动平均线

R数据帧中的布尔加法会产生布尔值而不是整值

使用scale_x_continuous复制ggplot 2中的离散x轴

在值和NA的行顺序中寻找中断模式

根据R中的另一个日期从多列中 Select 最近的日期和相应的结果

如何根据组大小应用条件过滤?

如何将dygraph调用到R Markdown作为一个shiny 的react 对象的参数?

我想在R中总结一个巨大的数据框架,使我只需要唯一的lat、lon、Date(Year)和Maxium Value""""""""

在R中将特定列的值向右移动

使用R闪光显示所有数据点作为默认设置

使用列/行匹配将两个不同维度的矩阵相加

按多列统计频次

过滤名称以特定字符串开头的文件

如何在ggplot2中创建多个y轴(每个变量一个)

R中时间间隔的大向量与参考时间间隔的相交

创建在文本字符串中发现两个不同关键字的实例的数据框

是否可以将线性模型的p值添加到tbl_summary中

Rmarkdown::Render vs Source()

roxygen2正在处理太多的文件

在REST API中使用参数R