BEARBEITEN: aktualisiert auf eine bessere moderne R-Antwort.
Sie können replicate()
dann rbind
das Ergebnis wieder zusammen verwenden. Die Rownamen werden automatisch so geändert, dass sie von 1: nrows ablaufen.
d <- data.frame(a = c(1,2,3),b = c(1,2,3))
n <- 3
do.call("rbind", replicate(n, d, simplify = FALSE))
Ein traditionellerer Weg ist die Verwendung der Indizierung, aber hier ist die Änderung des Rownamens nicht ganz so ordentlich (aber informativer):
d[rep(seq_len(nrow(d)), n), ]
Hier sind Verbesserungen gegenüber den oben genannten, die ersten beiden mit purrr
funktionaler Programmierung, idiomatisches Schnurren:
purrr::map_dfr(seq_len(3), ~d)
und weniger idiomatisches Schnurren (identisches Ergebnis, wenn auch umständlicher):
purrr::map_dfr(seq_len(3), function(x) d)
und schließlich über Indizierung statt Liste anwenden mit dplyr
:
d %>% slice(rep(row_number(), 3))
Für
data.frame
Objekte ist diese Lösung um ein Vielfaches schneller als die von @ mdsummer und @ wojciech-sobala.Bei
data.table
Objekten ist @ mdsummer's nach dem Konvertieren in etwas schneller als das Anwenden der oben genanntendata.frame
. Für große n könnte dies umdrehen. .Vollständiger Code:
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))
quelle
Das Paket
dplyr
enthält die Funktionbind_rows()
, die alle Datenrahmen in einer Liste direkt kombiniert, sodass keine Verwendungdo.call()
zusammen mitrbind()
:df <- data.frame(a = c(1, 2, 3), b = c(1, 2, 3)) library(dplyr) bind_rows(replicate(3, df, simplify = FALSE))
Denn eine große Anzahl von Wiederholungen
bind_rows()
ist auch viel schneller alsrbind()
: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
quelle
slice(rep(row_number(), 3))
ist besser, laut Max 'Benchmark. Oh, ich habe gerade Ihre Bank gesehen ... persönlich würde ich denken, dass eine Vergrößerung der DF etwas die richtige Richtung wäre, anstatt die Anzahl der Tische, aber ich weiß es nicht.slice(df, rep(row_number(), 3))
stellt sich heraus, dass es ein bisschen langsamer ist alsbind_rows(replicate(...))
(1,9 vs. 2,1 ms). Auf jeden Fall fand ich es nützlich, auch einedplyr
Lösung zu haben ...Mit dem Datentabelle-Paket, Sie könnten das spezielle Symbol
.I
zusammen mit verwendenrep
:df <- data.frame(a = c(1,2,3), b = c(1,2,3)) dt <- as.data.table(df) n <- 3 dt[rep(dt[, .I], n)]
was gibt:
quelle
df[, rep(seq_along(df), n)]
; Für eine Datentabelle könnten Sie Folgendes tun:cols <- rep(seq_along(mydf), n); mydf[, ..cols]
d <- data.frame(a = c(1,2,3),b = c(1,2,3)) r <- Reduce(rbind, list(d)[rep(1L, times=3L)])
quelle
Verwenden Sie einfach die einfache Indizierung mit Wiederholungsfunktion.
mydata<-data.frame(a = c(1,2,3),b = c(1,2,3)) #creating your data frame n<-10 #defining no. of time you want repetition of the rows of your dataframe mydata<-mydata[rep(rownames(mydata),n),] #use rep function while doing indexing rownames(mydata)<-1:NROW(mydata) #rename rows just to get cleaner look of data
quelle
Noch einfacher:
library(data.table) my_data <- data.frame(a = c(1,2,3),b = c(1,2,3)) rbindlist(replicate(n = 3, expr = my_data, simplify = FALSE)
quelle
data.table
Paket