122 votes

Répéter les lignes d'un data.frame

Je veux répéter les lignes d'un data.frame, chaque N fois. Le résultat devrait être un nouveau data.frame (avec nrow(new.df) == nrow(old.df) * N ) en conservant les types de données des colonnes.

Exemple pour 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

Ainsi, chaque ligne est répétée 2 fois et les caractères restent les caractères, les facteurs restent les facteurs, les chiffres restent les chiffres, ...

Ma première tentative d'utilisation de l'application : apply(old.df, 2, function(co) rep(co, each = N)) Mais celui-ci transforme mes valeurs en caractères et j'obtiens :

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

173voto

Josh O'Brien Points 68397
df <- data.frame(a = 1:2, b = letters[1:2]) 
df[rep(seq_len(nrow(df)), each = 2), ]

92voto

David Rubinger Points 723

Une propreté dplyr solution, tirée de aquí

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

33voto

Adam Erickson Points 44

Il existe une belle solution vectorielle qui ne répète que certaines lignes n fois chacune, possible par exemple en ajoutant un ntimes dans votre cadre de données :

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

Méthode :

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

Résultat :

  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

Cette méthode est très similaire à celle de Josh O'Brien et Mark Miller :

df[rep(seq_len(nrow(df)), df$ntimes),]

Toutefois, cette méthode semble un peu plus lente :

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
)

Résultat :

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

12voto

dardisco Points 1375

Si vous pouvez répéter l'ensemble, ou le sous-ensemble d'abord, puis le répéter, alors cette question similaire peut être utile. Encore une fois, je vous prie d'agréer, Monsieur le Président, l'expression de mes sentiments distingués :

library(mefa)
rep(mtcars,10) 

ou simplement

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

9voto

smci Points 2818

En complément de ce que @dardisco a mentionné à propos de mefa::rep.data.frame() Il est très flexible.

Vous pouvez soit répéter chaque ligne N fois :

rep(df, each=N)

o répéter l'ensemble de la base de données N fois (pensez : comme lorsque vous recyclez un argument vectorisé)

rep(df, times=N)

Deux pouces en l'air pour mefa ! Je n'en avais jamais entendu parler jusqu'à présent et j'ai dû écrire un code manuel pour le faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X