r dataframe rows repeat

Repite las filas de un data.frame



dataframe rows (9)

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.

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:

A B C A B C 1 j i 100 1 j i 100 --> 2 j i 100 2 K P 101 3 K P 101 4 K P 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 intento utilizado apply: apply(old.df, 2, function(co) rep(co, each = N)) , pero este transforma mis valores en caracteres y obtengo:

A B C [1,] "j" "i" "100" [2,] "j" "i" "100" [3,] "K" "P" "101" [4,] "K" "P" "101"


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) }


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.


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 a b 1 a d 2 b e 3 c f > as.data.frame(lapply(data, rep, 2)) a b 1 a d 2 b e 3 c f 4 a d 5 b e 6 c f


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)


Una solución dplyr limpia, tomada de here

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


intente usar, por ejemplo

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

como un índice


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