Đối data.frame
đối tượng, giải pháp này là nhiều nhanh hơn so với @ mdsummer's và @ wojciech-sobala's.
d[rep(seq_len(nrow(d)), n), ]
Đối data.table
đối tượng, @ mdsummer là nhanh hơn so với việc áp dụng trên sau khi chuyển đổi để data.frame
một chút. Đối với lớn n này có thể lật. .
Full mã:
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)
library(RUnit)
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
library(microbenchmark)
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)
library(ggplot2)
ggsave("~/gdrive/repeat_microbenchmark.png", autoplot(res))
Hãy coi chừng khung dữ liệu hàng không. seq_len có lẽ là một lựa chọn tốt hơn – hadley
Cảm ơn, tôi đã mơ hồ về điều đó (tôi luôn nghĩ rằng đó là seq_along và không nỗ lực). Tôi đánh giá cao những người đứng đầu. – mdsumner