Powtórz wiersze danych.ramka

Chcę powtórzyć wiersze danych.frame, każdy N razy. Wynikiem powinno być nowe data.frame (z nrow(new.df) == nrow(old.df) * N) zachowujące typy danych kolumn.

Przykład dla 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

Tak więc, każdy wiersz powtarza się 2 razy i znaki pozostają znakami, czynniki pozostają czynnikami, cyfry pozostają numerami, ...

Moja pierwsza próba zastosowana apply: apply(old.df, 2, function(co) rep(co, each = N)), ale ta zamienia moje wartości na znaki i otrzymuję:

     A   B   C    
[1,] "j" "i" "100"
[2,] "j" "i" "100"
[3,] "K" "P" "101"
[4,] "K" "P" "101"
Author: saladi, 2012-06-20

10 answers

df <- data.frame(a=1:2, b=letters[1:2]) 
df[rep(seq_len(nrow(df)), each=2),]
 94
Author: Josh O'Brien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 14:09:10

A clean dplyr solution, taken from here

library(dplyr)
df <- data_frame(x = 1:2, y = c("a", "b"))
df %>% slice(rep(1:n(), each = 2))
 11
Author: David Rubinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-12 19:53:47

Jeśli możesz powtórzyć całość, lub najpierw ją podgrupować, to powtórz to, to to podobne pytanie może być pomocne. Jeszcze raz:

library(mefa)
rep(mtcars,10) 

Lub po prostu

mefa:::rep.data.frame(mtcars)
 4
Author: dardisco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:00

Funkcja rep. row wydaje się czasami tworzyć listy dla kolumn, co prowadzi do złych przechwyceń pamięci. Napisałem co następuje, co wydaje się działać dobrze:

library(plyr)
rep.row <- function(r, n){
  colwise(function(x) rep(x, n))(r)
}
 4
Author: jebyrnes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-30 18:31:28

Dla odniesienia i dodania do odpowiedzi cytujących mefa, warto przyjrzeć się implementacji mefa::rep.data.frame() w przypadku, gdy nie chcesz dołączyć całego pakietu:

> 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
 4
Author: Fabio Gabriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-21 18:53:13

Dodając do tego, co @ dardisco wspomniał o mefa::rep.data.frame(), jest to bardzo elastyczne.

Możesz powtórzyć każdy wiersz N razy :

rep(df, each=N)

Lub powtórz całą ramkę danych N razy (pomyśl: jak wtedy, gdy przetwarzasz wektoryzowany argument)

rep(df, times=N)
Dwa kciuki do góry! Nigdy o tym nie słyszałem, aż do teraz i musiałem napisać kod ręczny, aby to zrobić.
 3
Author: smci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 02:23:22

Spróbuj użyć na przykład

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

Jako indeks

 1
Author: shhhhimhuntingrabbits,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 14:09:15

Moje rozwiązanie podobne do mefa:::rep.data.frame, ale trochę szybsze i dba o nazwy wierszy:

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
}

Porównaj rozwiązania:

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
 1
Author: Artem Klevtsov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 19:18:43

Istnieje piękne wektoryzowane rozwiązanie, które powtarza tylko niektóre wiersze n-razy każdy, możliwe na przykład przez dodanie kolumny ntimes do ramki danych:

  A B   C ntimes
1 j i 100      2
2 K P 101      4
3 Z Z 102      1

Metoda:

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

Wynik:

  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
Jest to bardzo podobne do metody Josha O ' Briena i Marka Millera:]}
df[rep(seq_len(nrow(df)), df$ntimes),]

Jednak ta metoda wydaje się nieco wolniejsza:

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
)

Wynik:

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
 1
Author: Adam Erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 15:30:10

Innym sposobem na to jest najpierw uzyskanie indeksów wierszy, dołączenie dodatkowych kopii df, a następnie uporządkowanie według indeksów:

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

Chociaż inne rozwiązania mogą być krótsze, metoda ta może być bardziej korzystna w pewnych sytuacjach.

 0
Author: crazjo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-03 12:07:56