2014-12-06 11 views
5

Ho una tabella di dati come questa.Assegnazione di valori in una sequenza a seconda della riga precedente in R

ID1 ID2 member 
1 a x parent 
2 a y child 
3 a z parent 
4 a p child 
5 a q child 
6 b x parent 
7 b z parent 
8 b q child 

E voglio assegnare una sequenza come di seguito.

ID1 ID2 member sequence 
1 a x parent  1 
2 a y child  2 
3 a z parent  1 
4 a p child  2 
5 a q child  3 
6 b x parent  1 
7 b z parent  1 
8 b q child  2 

cioè

> dt$sequence = 1, wherever dt$member == "parent" 

> dt$sequence = previous_row_value + 1, wherever dt$member=="child" 

A partire da ora che ho fatto usando loop, come qui di seguito.

dt_sequence <- dt[ ,sequencing(.SD), by="ID1"] 

sequencing <- function(dt){ 
    for(i in 1:nrow(dt)){ 
    if(i == 1){ 
     dt$sequence[i] = 1 
     next 
    } 
    if(dt[i,member] %in% "child"){ 
     dt$sequence[i] = as.numeric(dt$sequence[i-1]) + 1 
    } 
    else 
     dt$sequence[i] = 1 
    } 
    return(dt) 
} 

ho eseguito questo codice su una tabella di dati di 400 000 righe e ci sono voluti un sacco di tempo per completare (circa 15 minuti). Qualcuno può suggerire un modo più veloce per farlo.

risposta

5

Ecco un modo con seq:

dt[ , sequence := seq(.N), by = cumsum(member == "parent")] 

# ID1 ID2 member sequence 
# 1: a x parent  1 
# 2: a y child  2 
# 3: a z parent  1 
# 4: a p child  2 
# 5: a q child  3 
# 6: b x parent  1 
# 7: b z parent  1 
# 8: b q child  2 

Come funziona?

Il comando member == "parent" crea un vettore logico. La funzione cumsum viene utilizzata per calcolare la somma cumulativa. In questo caso, crea un vettore in cui un genitore e i seguenti figli hanno lo stesso numero. Questo vettore è utilizzato per il raggruppamento. Infine, seq(.N) crea una sequenza da 1 fino al numero di elementi nel gruppo.

+1

Potete spiegarlo per favore? – shubham

+0

@ShubhamMittal Vedere l'aggiornamento. –

Problemi correlati