Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance R中merge.data.frame()的更快实现_Performance_R_Dataframe - Fatal编程技术网

Performance R中merge.data.frame()的更快实现

Performance R中merge.data.frame()的更快实现,performance,r,dataframe,Performance,R,Dataframe,假设a和b是两个数据帧。目标是编写一个函数 f(a,b)以与merge相同的方式生成合并数据帧 merge(a,b,all=TRUE)就可以了,那就是用NAs填充a或b中缺少的变量。(问题是merge()似乎非常慢。) 这可以按如下方式完成(伪代码): 然后将所有内容包装在数据框中 下面是一个“幼稚”的实现: merge.datasets1 <- function(a, b) { a.fill <- rep(NA, nrow(a)) b.fill <- rep(NA,

假设
a
b
是两个数据帧。目标是编写一个函数
f(a,b)
以与merge相同的方式生成合并数据帧
merge(a,b,all=TRUE)
就可以了,那就是用NAs填充
a
b
中缺少的变量。(问题是
merge()
似乎非常慢。)

这可以按如下方式完成(伪代码):

然后将所有内容包装在数据框中

下面是一个“幼稚”的实现:

merge.datasets1 <- function(a, b) {
  a.fill <- rep(NA, nrow(a))
  b.fill <- rep(NA, nrow(b))
  a.fill.factor <- as.factor(a.fill)
  b.fill.factor <- as.factor(b.fill)
  out <- list()
  for (v in union(names(a), names(b))) {
    if (!v %in% names(a)) {
      b.srcvar <- b[[v]]
      if (is.factor(b.srcvar))
        a.srcvar <- a.fill.factor
      else
        a.srcvar <- a.fill
    } else {
      a.srcvar <- a[[v]]
      if (v %in% names(b))
        b.srcvar <- b[[v]]
      else if (is.factor(a.srcvar))
        b.srcvar <- b.fill.factor
      else
        b.srcvar <- b.fill
    }
    out[[v]] <- unlist(list(a.srcvar, b.srcvar),
                       recursive=FALSE, use.names=FALSE)
  }
  data.frame(out)
}

merge.datasets1事实上,您根本没有尝试复制
merge(a,b,all=TRUE)
,因为您没有尝试在任何列上进行合并。相反,您只是简单地堆叠数据,在不存在列的地方填充
NA

 # note  that this is not what you want/
dim(merge(sample.datasets[[1]], sample.datasets[[2]], all = T))
 [1] 314   5
merge(a,b,all=TRUE)
速度较慢的原因是它默认通过名称的交集进行合并。如果您转换为
data.tables
,则
merge.data.table
方法的速度非常快,但对于您的测试数据,它将在每次成功合并时创建一个指数级增长的数据集(而不是您希望的7500乘5)

一个简单的解决方案是使用
plyr
包中的
rbind.fill

library(plyr)
system.time({.x <- Reduce(rbind.fill, sample.datasets)})
## user  system elapsed 
## 0.16    0.00    0.15 
# which is almost identical to
system.time(.old <- Reduce(merge.datasets1, sample.datasets))
##   user  system elapsed 
##   0.14    0.00    0.14 

花费在
Reduce
的管理费用上的大部分时间,而
rbind.fill
并不需要。

事实上,您根本没有尝试复制
合并(a,b,all=TRUE)
,因为您没有尝试在任何列上进行合并。相反,您只是简单地堆叠数据,在不存在列的地方填充
NA

 # note  that this is not what you want/
dim(merge(sample.datasets[[1]], sample.datasets[[2]], all = T))
 [1] 314   5
merge(a,b,all=TRUE)
速度较慢的原因是它默认通过名称的交集进行合并。如果您转换为
data.tables
,则
merge.data.table
方法的速度非常快,但对于您的测试数据,它将在每次成功合并时创建一个指数级增长的数据集(而不是您希望的7500乘5)

一个简单的解决方案是使用
plyr
包中的
rbind.fill

library(plyr)
system.time({.x <- Reduce(rbind.fill, sample.datasets)})
## user  system elapsed 
## 0.16    0.00    0.15 
# which is almost identical to
system.time(.old <- Reduce(merge.datasets1, sample.datasets))
##   user  system elapsed 
##   0.14    0.00    0.14 

花费在
Reduce
开销上的大部分时间,这
rbind.fill
不需要。

使用
数据。table
。因为循环本身并不慢,如果合理使用,特别是在预分配内存的情况下,不要在循环中扩展对象,等等。@JoshuaUlrich
data.table
不起作用,因为它的
merge
方法在生成的数据中不包含非公共变量。table.你看过了吗:我愿意打赌有一种方法可以处理
数据。table
。使用
数据。table
。因为循环本身并不慢,如果您合理地使用它们,特别是在预先分配内存的情况下,不要在循环中扩展对象,等等。@JoshuaUlrich
data.table
不起作用,因为它的
merge
方法在结果data.table中不包含非公共变量。你看过这个了吗:我愿意打赌,有一种方法可以处理
data.table
library(plyr)
system.time({.x <- Reduce(rbind.fill, sample.datasets)})
## user  system elapsed 
## 0.16    0.00    0.15 
# which is almost identical to
system.time(.old <- Reduce(merge.datasets1, sample.datasets))
##   user  system elapsed 
##   0.14    0.00    0.14 
 system.time(super_fast <- rbind.fill(sample.datasets))
 ##  user  system elapsed 
 ##  0.02    0.00    0.02 

identical(super_fast, .old)
[1] TRUE