2015-03-10 19 views
7

Ho un data.table che assomiglia a questocreare righe duplicate in base alle condizioni in R

dt <- data.table(ID=c("A","A","B","B"),Amount1=c(100,200,300,400), 
       Amount2=c(1500,1500,2400,2400),Dupl=c(1,0,1,0)) 

    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A  200 1500 0 
3: B  300 2400 1 
4: B  400 2400 0 

ho bisogno di duplicare ogni riga che ha un 1 nella colonna Dupl e sostituire il valore amount1 con l'AMOUNT2 valore in quella riga duplicata. Oltre a questo ho bisogno di dare a quella riga duplicata il valore 2 in Dupl. Questo significa che dovrebbe apparire così:

ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A 1500 1500 2 
3: A  200 1500 0 
4: B  300 2400 1 
5: B 2400 2400 2 
6: B  400 2400 0 

Qualsiasi aiuto è molto apprezzato! Cordiali saluti,

Tim

+3

Esistono altre regole che è necessario conoscere? Potrebbero esserci quattro righe per un dato ID? La colonna "Dupl" ha valori diversi da "1" e "2"? – A5C1D2H2I1M1N2O1R2T1

risposta

9

Si potrebbe provare

rbind(dt,dt[Dupl==1][,c('Amount1', 'Dupl') := list(Amount2, 2)]) 
+0

@DavidArenburg Grazie, stavo anche pensando in termini di 'rleid' usando il codice del template, ma ho trovato un po 'difficile. – akrun

3

Questo sembra fare quello che stai chiedendo. Può forse essere raffinato un po '...

library(splitstackshape) 
expandRows(dt, dt$Dupl+1, count.is.col = FALSE)[ 
    Dupl != 0, Dupl := cumsum(Dupl), by = ID][ 
    , Amount1 := ifelse(Dupl > 1, Amount2[-1], Amount1)][] 
# ID Amount1 Amount2 Dupl 
# 1: A  100 1500 1 
# 2: A 1500 1500 2 
# 3: A  200 1500 0 
# 4: B  300 2400 1 
# 5: B 2400 2400 2 
# 6: B  400 2400 0 
6

Utilizzando dplyr

require("data.table") 
require("dplyr") 

#data 
dt <- data.table(ID=c("A","A","B","B"),Amount1=c(100,200,300,400), 
       Amount2=c(1500,1500,2400,2400),Dupl=c(1,0,1,0)) 
#result 
rbind(dt, 
     dt %>% 
     filter(Dupl==1) %>% 
     mutate(Dupl=2, 
       Amount1=Amount2)) 

# ID Amount1 Amount2 Dupl 
# 1: A  100 1500 1 
# 2: A  200 1500 0 
# 3: B  300 2400 1 
# 4: B  400 2400 0 
# 5: A 1500 1500 2 
# 6: B 2400 2400 2 
+0

Cerco sempre di evitare plyr poiché lavoro con dataset di grandi dimensioni, ma anche questo ha funzionato. Grazie molto. –

4

È possibile rbind una copia dei dati di sub-Setted con le trasformazioni corrette terminato:

rbind(dt,copy(dt[Dupl==1])[,Amount1:=Amount2][,Dupl:=Dupl+1]) 
    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A  200 1500 0 
3: B  300 2400 1 
4: B  400 2400 0 
5: A 1500 1500 2 
6: B 2400 2400 2 

In alternativa, è possibile ottenere i duplicati impostando i valori secondari e quindi trasformare le righe duplicate utilizzando un passaggio intermedio. Ciò mantiene la riga duplicata accanto all'originale come nell'esempio nella domanda:

x <- dt[rep(seq(dt[,Dupl]),times=dt[,Dupl==1]+1)] 
x[duplicated(x),c("Amount1","Dupl"):=list(Amount2,Dupl+1)] 
x 
    ID Amount1 Amount2 Dupl 
1: A  100 1500 1 
2: A 1500 1500 2 
3: A  200 1500 0 
4: B  300 2400 1 
5: B 2400 2400 2 
6: B  400 2400 0 
+1

È possibile eseguire il primo passaggio nella seconda soluzione solo con 'x <- dt [rep (seq_len (.N), Dupl + 1L)]'. Sembra che chiamare 'dt' 3 volte in questo singolo passo sia un grosso overhead se' dt' è grande. –

Problemi correlati