Repite las filas de un data.frame

Quiero repetir las filas de un data.frame, cada N veces. El resultado debe ser un nuevo data.frame (con nrow(new.df) == nrow(old.df) * N ) manteniendo los tipos de datos de las columnas.

Ejemplo para N = 2:

  ABC ABC 1 ji 100 1 ji 100 --> 2 ji 100 2 KP 101 3 KP 101 4 KP 101 

Entonces, cada fila se repite 2 veces y los caracteres se mantienen, los factores siguen siendo factores, los números siguen siendo numéricos, …

Mi primer bash utilizado apply: apply(old.df, 2, function(co) rep(co, each = N)) , pero este transforma mis valores en caracteres y obtengo:

  ABC [1,] "j" "i" "100" [2,] "j" "i" "100" [3,] "K" "P" "101" [4,] "K" "P" "101" 

     df < - data.frame(a=1:2, b=letters[1:2]) df[rep(seq_len(nrow(df)), each=2),] 

    Una solución dplyr limpia, tomada de aquí

     library(dplyr) df < - data_frame(x = 1:2, y = c("a", "b")) df %>% slice(rep(1:n(), each = 2)) 

    Si puede repetir todo o subconjunto primero y luego repetirlo, esta pregunta similar puede ser útil. Una vez más:

     library(mefa) rep(mtcars,10) 

    o simplemente

     mefa:::rep.data.frame(mtcars) 

    La función rep.row parece a veces hacer listas para columnas, lo que conduce a hijinks de mala memoria. He escrito lo siguiente que parece funcionar bien:

     library(plyr) rep.row < - function(r, n){ colwise(function(x) rep(x, n))(r) } 

    Para referencia y agregar respuestas que citan mefa, vale la pena echar un vistazo a la implementación de mefa::rep.data.frame() en caso de que no desee incluir todo el paquete:

     > data < - data.frame(a=letters[1:3], b=letters[4:6]) > data ab 1 ad 2 be 3 cf > as.data.frame(lapply(data, rep, 2)) ab 1 ad 2 be 3 cf 4 ad 5 be 6 cf 

    Agregando a lo que @dardisco mencionó sobre mefa::rep.data.frame() , es muy flexible.

    Puedes repetir cada fila N veces :

     rep(df, each=N) 

    o repita todo el dataframe N veces (piense: como cuando recicla un argumento vectorizado)

     rep(df, times=N) 

    ¡Dos pulgares arriba para mefa ! Nunca había oído hablar de él hasta ahora y tuve que escribir el código manual para hacer esto.

    intente usar, por ejemplo

     N=2 rep(1:4, each = N) 

    como un índice

    Mi solución es similar a mefa:::rep.data.frame , pero un poco más rápido y se preocupa por los nombres de las filas:

     rep.data.frame < - function(x, times) { rnames <- attr(x, "row.names") x <- lapply(x, rep.int, times = times) class(x) <- "data.frame" if (!is.numeric(rnames)) attr(x, "row.names") <- make.unique(rep.int(rnames, times)) else attr(x, "row.names") <- .set_row_names(length(rnames) * times) x } 

    Compare soluciones:

     library(Lahman) library(microbenchmark) microbenchmark( mefa:::rep.data.frame(Batting, 10), rep.data.frame(Batting, 10), Batting[rep.int(seq_len(nrow(Batting)), 10), ], times = 10 ) #> Unit: milliseconds #> expr min lq mean median uq max neval cld #> mefa:::rep.data.frame(Batting, 10) 127.77786 135.3480 198.0240 148.1749 278.1066 356.3210 10 a #> rep.data.frame(Batting, 10) 79.70335 82.8165 134.0974 87.2587 191.1713 307.4567 10 a #> Batting[rep.int(seq_len(nrow(Batting)), 10), ] 895.73750 922.7059 981.8891 956.3463 1018.2411 1127.3927 10 b 

    Otra forma de hacer esto sería obtener primero los índices de fila, anexar copias adicionales de la df, y luego ordenar por los índices:

     df$index = 1:nrow(df) df = rbind(df,df) df = df[order(df$index),][,-ncol(df)] 

    Aunque las otras soluciones pueden ser más cortas, este método puede ser más ventajoso en ciertas situaciones.