Повторите строки данных.рамка
Я хочу повторить строки данных.кадр, каждый N
раза. Результат должен быть новый data.frame
(С nrow(new.df) == nrow(old.df) * N
) сохранение типов данных столбцов.
пример для 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
Итак, каждая строка повторяется 2 раза и символы остаются символами, факторы остаются факторами, цифры остаются цифрами ...
моя первая попытка применяется:apply(old.df, 2, function(co) rep(co, each = N))
, но этот преобразует мои значения в символы, и я получаю:
A B C
[1,] "j" "i" "100"
[2,] "j" "i" "100"
[3,] "K" "P" "101"
[4,] "K" "P" "101"
10 ответов:
чистой
dplyr
решение, принятое от здесьlibrary(dplyr) df <- data_frame(x = 1:2, y = c("a", "b")) df %>% slice(rep(1:n(), each = 2))
Если вы можете повторить все это, или подмножество его сначала, потом повторить, потом этот же вопрос может быть полезным. Еще раз:
library(mefa) rep(mtcars,10)
или просто
mefa:::rep.data.frame(mtcars)
функция rep. row, похоже, иногда создает списки для столбцов, что приводит к плохим ссылкам на память. Я написал следующее, что, кажется, работает хорошо:
library(plyr) rep.row <- function(r, n){ colwise(function(x) rep(x, n))(r) }
для справки и добавления к ответам со ссылкой на mefa, возможно, стоит взглянуть на реализацию
mefa::rep.data.frame()
в случае, если вы не хотите включать весь пакет:> 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
добавление к тому, что @dardisco упомянул о
mefa::rep.data.frame()
, это очень гибкая.вы можете повторите каждую строку N раз:
rep(df, each=N)
или повторите весь кадр данных N раз (подумайте: например, когда вы перерабатываете векторизованный аргумент)
rep(df, times=N)
два больших пальца вверх для
mefa
! Я никогда не слышал об этом до сих пор, и мне пришлось написать ручной код, чтобы сделать это.
мое решение похоже на
mefa:::rep.data.frame
, но немного быстрее и заботится о имена строк: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 }
Сравни решения:
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
есть прекрасное векторизованное решение, которое повторяет только определенные строки n-раз каждый, возможно, например, добавив
ntimes
столбец в ваш фрейм данных:A B C ntimes 1 j i 100 2 2 K P 101 4 3 Z Z 102 1
способ:
df <- data.frame(A=c("j","K","Z"), B=c("i","P","Z"), C=c(100,101,102), ntimes=c(2,4,1)) df <- as.data.frame(lapply(df, rep, df$ntimes))
результат:
A B C ntimes 1 Z Z 102 1 2 j i 100 2 3 j i 100 2 4 K P 101 4 5 K P 101 4 6 K P 101 4 7 K P 101 4
это очень похоже на метод Джоша О'Брайена и Марка Миллера:
df[rep(seq_len(nrow(df)), df$ntimes),]
однако, этот метод выглядит довольно медленнее:
df <- data.frame(A=c("j","K","Z"), B=c("i","P","Z"), C=c(100,101,102), ntimes=c(2000,3000,4000)) microbenchmark::microbenchmark( df[rep(seq_len(nrow(df)), df$ntimes),], as.data.frame(lapply(df, rep, df$ntimes)), times = 10 )
результат:
Unit: microseconds expr min lq mean median uq max neval df[rep(seq_len(nrow(df)), df$ntimes), ] 3563.113 3586.873 3683.7790 3613.702 3657.063 4326.757 10 as.data.frame(lapply(df, rep, df$ntimes)) 625.552 654.638 676.4067 668.094 681.929 799.893 10
другой способ сделать это-сначала получить индексы строк, добавить дополнительные копии df, а затем упорядочить по индексам:
df$index = 1:nrow(df) df = rbind(df,df) df = df[order(df$index),][,-ncol(df)]
хотя другие решения могут быть короче, этот метод может быть более выгодным в определенных ситуациях.