2016-07-09 40 views
7

Questo è ciò che la mia tabella di dati si presenta come:Prendi l'ultima riga di un gruppo precedente data.table

library(data.table) 
dt <- fread(' 
    Product Group LastProductOfPriorGroup 
    A   1   NA 
    B   1   NA 
    C   2   B 
    D   2   B 
    E   2   B 
    F   3   E 
    G   3   E 
') 

La colonna LastProductOfPriorGroup è la mia colonna desiderata. Sto cercando di recuperare il prodotto dall'ultima riga del gruppo precedente. Quindi nelle prime due righe non ci sono gruppi precedenti e quindi è NA. Nella terza riga, il prodotto nell'ultima riga del gruppo precedente 1 è B. Sto provando a realizzare questo da

dt[,LastGroupProduct:= shift(Product,1), by=shift(Group,1)] 

inutilmente.

risposta

14

Si potrebbe fare

dt[, newcol := shift(dt[, last(Product), by = Group]$V1)[.GRP], by = Group] 

Il risultato è il seguente aggiornamento dt, dove newcol corrisponde la colonna desiderata con il nome inutilmente lungo. ;)

Product Group LastProductOfPriorGroup newcol 
1:  A  1      NA  NA 
2:  B  1      NA  NA 
3:  C  2      B  B 
4:  D  2      B  B 
5:  E  2      B  B 
6:  F  3      E  E 
7:  G  3      E  E 

Rompiamo il codice dall'interno verso l'esterno. Userò ... per indicare il codice accumulato:

  • dt[, last(Product), by = Group]$V1 sta ottenendo gli ultimi valori di ogni gruppo come un vettore di carattere.
  • shift(...) sposta il vettore di carattere nella chiamata precedente
  • dt[, newcol := ...[.GRP], by = Group] gruppi da Group e utilizza i .GRP valori interni per l'indicizzazione

Aggiornamento: Frank porta in primo piano un buon punto per il mio codice di cui sopra calcolare lo spostamento per ogni gruppo più e più volte. Per evitare ciò, possiamo utilizzare

shifted <- shift(dt[, last(Product), Group]$V1) 
dt[, newcol := shifted[.GRP], by = Group] 

in modo da non calcolare lo spostamento per ogni gruppo. Oppure, possiamo prendere il bel suggerimento di Frank nei commenti e fare quanto segue.

+0

Si sta utilizzando per = Gruppo 2 volte. Qual è il primo a fare il 2 °? e qual è il significato di $ V1? – gibbz00

+1

@ gibbz00 - Ho aggiunto qualche spiegazione. Spero che sia d'aiuto. –

+1

Si sta calcolando 'shift (dt [, last (Product), da = Group] $ V1)' ancora e ancora per ogni gruppo. Probabilmente farei 'dt [dt [, last (Prodotto), per = Gruppo] [, v: = shift (V1)], on =" Gruppo ", newcol: = iv]' – Frank

7

Un altro modo è salvare il valore dell'ultimo gruppo in una variabile.

this = NA_character_ # initialize 
dt[, LastProductOfPriorGroup:={ last<-this; this<-last(Product); last }, by=Group] 
dt 
    Product Group LastProductOfPriorGroup 
1:  A  1      NA 
2:  B  1      NA 
3:  C  2      B 
4:  D  2      B 
5:  E  2      B 
6:  F  3      E 
7:  G  3      E 

NB: last() è una funzione data.table che restituisce l'ultimo elemento di un vettore (della colonna Prodotto in questo caso).

Questo dovrebbe anche essere veloce poiché non viene invocata alcuna logica per recuperare il valore dell'ultimo gruppo; si basa solo sui gruppi in esecuzione in ordine (cosa che fanno).