首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重复data.frame N次的行

重复data.frame N次的行
EN

Stack Overflow用户
提问于 2012-01-06 04:53:07
回答 8查看 96.5K关注 0票数 101

我有以下数据框架:

代码语言:javascript
复制
data.frame(a = c(1,2,3),b = c(1,2,3))
  a b
1 1 1
2 2 2
3 3 3

我想重复这几行。例如,在这里,行被重复3次:

代码语言:javascript
复制
  a b
1 1 1
2 2 2
3 3 3
4 1 1
5 2 2
6 3 3
7 1 1
8 2 2
9 3 3

在R中有一个简单的函数可以这样做吗?谢谢!

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-01-06 05:23:35

编辑:更新到一个更好的现代R答案。

您可以使用replicate(),然后将结果重新组合在一起。行名将自动更改为从1:nrow运行。

代码语言:javascript
复制
d <- data.frame(a = c(1,2,3),b = c(1,2,3))
n <- 3
do.call("rbind", replicate(n, d, simplify = FALSE))

一种更传统的方法是使用索引,但是这里的行名更改并不是很整洁(但更有信息):

代码语言:javascript
复制
 d[rep(seq_len(nrow(d)), n), ]

下面是对上面的改进,前两个使用purrr函数式编程,惯用purrr:

代码语言:javascript
复制
purrr::map_dfr(seq_len(3), ~d)

和不那么惯用的咕噜声(相同的结果,虽然更尴尬):

代码语言:javascript
复制
purrr::map_dfr(seq_len(3), function(x) d)

最后,通过索引而不是列表使用dplyr应用

代码语言:javascript
复制
d %>% slice(rep(row_number(), 3))
票数 180
EN

Stack Overflow用户

发布于 2015-02-13 18:55:46

对于data.frame对象,该解决方案比@mdsummer和@wojciech的快几倍。

代码语言:javascript
复制
d[rep(seq_len(nrow(d)), n), ]

对于data.table对象,@mdsummer的应用比转换为data.frame后的应用要快一些。对于大的n,这可能会翻转。

完整代码:

代码语言:javascript
复制
packages <- c("data.table", "ggplot2", "RUnit", "microbenchmark")
lapply(packages, require, character.only=T)

Repeat1 <- function(d, n) {
  return(do.call("rbind", replicate(n, d, simplify = FALSE)))
}

Repeat2 <- function(d, n) {
  return(Reduce(rbind, list(d)[rep(1L, times=n)]))
}

Repeat3 <- function(d, n) {
  if ("data.table" %in% class(d)) return(d[rep(seq_len(nrow(d)), n)])
  return(d[rep(seq_len(nrow(d)), n), ])
}

Repeat3.dt.convert <- function(d, n) {
  if ("data.table" %in% class(d)) d <- as.data.frame(d)
  return(d[rep(seq_len(nrow(d)), n), ])
}

# Try with data.frames
mtcars1 <- Repeat1(mtcars, 3)
mtcars2 <- Repeat2(mtcars, 3)
mtcars3 <- Repeat3(mtcars, 3)

checkEquals(mtcars1, mtcars2)
#  Only difference is row.names having ".k" suffix instead of "k" from 1 & 2
checkEquals(mtcars1, mtcars3)

# Works with data.tables too
mtcars.dt <- data.table(mtcars)
mtcars.dt1 <- Repeat1(mtcars.dt, 3)
mtcars.dt2 <- Repeat2(mtcars.dt, 3)
mtcars.dt3 <- Repeat3(mtcars.dt, 3)

# No row.names mismatch since data.tables don't have row.names
checkEquals(mtcars.dt1, mtcars.dt2)
checkEquals(mtcars.dt1, mtcars.dt3)

# Time test
res <- microbenchmark(Repeat1(mtcars, 10),
                      Repeat2(mtcars, 10),
                      Repeat3(mtcars, 10),
                      Repeat1(mtcars.dt, 10),
                      Repeat2(mtcars.dt, 10),
                      Repeat3(mtcars.dt, 10),
                      Repeat3.dt.convert(mtcars.dt, 10))
print(res)
ggsave("repeat_microbenchmark.png", autoplot(res))
票数 43
EN

Stack Overflow用户

发布于 2017-08-11 15:30:22

dplyr包含函数bind_rows(),该函数直接组合列表中的所有数据帧,因此不需要将do.call()rbind()一起使用。

代码语言:javascript
复制
df <- data.frame(a = c(1, 2, 3), b = c(1, 2, 3))
library(dplyr)
bind_rows(replicate(3, df, simplify = FALSE))

对于大量重复,bind_rows()也比rbind()快得多

代码语言:javascript
复制
library(microbenchmark)
microbenchmark(rbind = do.call("rbind", replicate(1000, df, simplify = FALSE)),
               bind_rows = bind_rows(replicate(1000, df, simplify = FALSE)),
               times = 20)
## Unit: milliseconds
##       expr       min        lq      mean   median        uq       max neval cld
##      rbind 31.796100 33.017077 35.436753 34.32861 36.773017 43.556112    20   b
##  bind_rows  1.765956  1.818087  1.881697  1.86207  1.898839  2.321621    20  a 
票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8753531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档