首页 > 解决方案 > 复制data.frame的最快方法

问题描述

我正在寻找最快的复制data.frame。有没有rep.data.frame复制行?为所有输入实现这一目标的最快方法是什么?因为我有一个函数需要复制一个x可以是 avector或 a的对象data.frame

我目前使用的代码

repx <- function(x, ...) if(is.atomic(x)) rep(x, ...) else x[rep(1:nrow(x), ...),]

我使用@ronak 的答案提出了一个足够接近的解决方案,尽管我的目标是获得与 rep 类似的输出,请参见下面的输出:

rep.data.frame <- function(x, each, times) rbindlist(replicate(times, rbindlist(replicate(each, x, simplify = F) ), simplify = F) )

rep(data.frame(y=1:2), times=3, each=2)
    y
 1: 1
 2: 2
 3: 1
 4: 2
 5: 1
 6: 2
 7: 1
 8: 2
 9: 1
10: 2
11: 1
12: 2

# Desired output
    x
 1: 1
 2: 1
 3: 2
 4: 2
 5: 1
 6: 1
 7: 2
 8: 2
 9: 1
10: 1
11: 2
12: 2

标签: rdataframerep

解决方案


您可以编写一个简单的函数,该函数将重复 adata.frame或向量的行等于指定的次数(这实际上与您已经在做的非常相似。请注意,我无法获得rep.data.frame所需的输出)。一个简单的函数可能如下所示:

rep_rows <- function(x, times) {
  if (is.matrix(x) | is.data.frame(x)) {
    x[rep(seq_len(nrow(x)), each = times), , drop = FALSE]
  } else {
    x[rep(seq_len(length(x)), each = times)]
  }
}

让我们创建两个对象来测试代码:

db <- data.frame(
  y = rep(1:2, times = 3)
)

y <- rep(1:2, times = 3)

db看起来像这样:

> db
  y
1 1
2 2
3 1
4 2
5 1
6 2

y看起来像这样:

> y
[1] 1 2 1 2 1 2

使用我们的函数,我们得到:

> rep_rows(db, 2)
    y
1   1
1.1 1
2   2
2.1 2
3   1
3.1 1
4   2
4.1 2
5   1
5.1 1
6   2
6.1 2
> 

> rep_rows(y, 2)
 [1] 1 1 2 2 1 1 2 2 1 1 2 2

编辑:当以更大的数据为基准时,它仍然相当快。古玩看看它与其他方法的比较。

> db <- data.frame(
+   y = rep(1:5, times = 1000)
+ )
> microbenchmark::microbenchmark(rep_rows(db, 100))
Unit: milliseconds
              expr      min       lq    mean   median       uq      max neval
 rep_rows(db, 100) 259.0079 279.6223 294.129 285.9272 307.0718 349.6123   100 

推荐阅读