Повторите строки data.frame

Я хочу повторить строки data.frame каждый раз N. Результатом должен быть новый data.framenrow(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"
64 голоса | спросил Stefan 20 J0000006Europe/Moscow 2012, 18:04:47

10 ответов


0
df <- data.frame(a=1:2, b=letters[1:2]) 
df[rep(seq_len(nrow(df)), each=2),]
ответил Josh O'Brien 20 J0000006Europe/Moscow 2012, 18:09:10
0

Чистое dplyr решение, взятое из здесь

library(dplyr)
df <- data_frame(x = 1:2, y = c("a", "b"))
df %>% slice(rep(1:n(), each = 2))
ответил David Rubinger 12 TueEurope/Moscow2017-12-12T22:53:47+03:00Europe/Moscow12bEurope/MoscowTue, 12 Dec 2017 22:53:47 +0300 2017, 22:53:47
0

Если вы можете повторить все это или сначала сделать это, затем этот похожий вопрос может оказаться полезным. Еще раз:

library(mefa)
rep(mtcars,10) 

или просто

mefa:::rep.data.frame(mtcars)
ответил dardisco 25 AMpThu, 25 Apr 2013 02:20:31 +040020Thursday 2013, 02:20:31
0

Кажется, что функция rep.row иногда создает списки для столбцов, что приводит к неправильному отображению памяти. Я написал следующее, что, кажется, работает хорошо:

library(plyr)
rep.row <- function(r, n){
  colwise(function(x) rep(x, n))(r)
}
ответил jebyrnes 30 Maypm13 2013, 22:31:28
0

Для справки и добавления ответов, ссылающихся на 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
ответил Fabio Gabriel 21 J000000Tuesday15 2015, 21:53:13
0

Добавление к тому, что @dardisco упомянуло о mefa::rep.data.frame(), очень гибко.

Вы можете повторить каждую строку N раз :

rep(df, each=N)

или повторите весь кадр данных N раз (подумайте: например, когда вы перезаписываете векторизованный аргумент)

rep(df, times=N)

Два больших пальца для mefa! Я никогда не слышал об этом до сих пор, и мне пришлось написать ручной код, чтобы сделать это.

ответил smci 20 Mayam14 2014, 06:23:22
0

Мое решение похоже на 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
ответил Artem Klevtsov 1 MarpmTue, 01 Mar 2016 20:15:23 +03002016-03-01T20:15:23+03:0008 2016, 20:15:23
0

Существует прекрасное векторизованное решение, которое повторяет только определенные строки 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
ответил Adam Erickson 13 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 13 Sep 2018 03:49:36 +0300 2018, 03:49:36
0

попробуйте использовать, например,

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

в качестве индекса

ответил shhhhimhuntingrabbits 20 J0000006Europe/Moscow 2012, 18:09:15
0

Другой способ сделать это - сначала получить индексы строк, добавить дополнительные копии df, а затем упорядочить по индексам:

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

Хотя другие решения могут быть короче, этот метод может быть более выгодным в определенных ситуациях.

ответил crazjo 3 J0000006Europe/Moscow 2015, 15:07:56

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132