2014-10-19 11 views
5
library(data.table) 
DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C")) 
DT2 <- data.table(group = c("A", "B", "C")) 

voglio aggiungere una colonna popular-DT2 con valore TRUE ogni volta DT2$group è contenuto in DT1$group almeno due volte. Così, nell'esempio di cui sopra, dovrebbe essere DT2Controllare la frequenza di valore data.table in altri data.table

group popular 
1:  A TRUE 
2:  B TRUE 
3:  C FALSE 

quello che sarebbe un modo efficace per arrivare a questo?

esempio Aggiornato:DT2 può effettivamente contenere più gruppi di DT1, ecco un esempio aggiornato:

DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C")) 
DT2 <- data.table(group = c("A", "B", "C", "D")) 

E l'output desiderato sarebbe

group popular 
1:  A TRUE 
2:  B TRUE 
3:  C FALSE 
4:  D FALSE 
+1

'' DT2' ha sempre lo stesso 'gruppo' unico da' DT1'? Se è così, è semplicemente 'DT1 [,. (Popolare = .N> = 2L), per = gruppo]' – Arun

+0

Ciao @Arun, no non lo fa; Ho semplificato l'esempio qui, mi dispiace. '' DT2'' può contenere più gruppi di '' DT1'', nel qual caso popolare dovrebbe essere '' FALSE'' (dato che non è contenuto in '' DT1 $ group'' almeno due volte). – johnl

+0

+1 per una domanda ben formulata –

risposta

10

avevo appena fare in questo modo:

## 1.9.4+ 
setkey(DT1, group) 
DT1[J(DT2$group), list(popular = .N >= 2L), by = .EACHI] 
# group popular 
# 1:  A TRUE 
# 2:  B TRUE 
# 3:  C FALSE 
# 4:  D FALSE ## on the updated example 

data.table 's join sintassi è abbastanza potente, in quanto, mentre l'adesione, si può anche colonne/aggiornamento selezionare aggregati/a j. Qui eseguiamo un join. Per ogni riga in DT2$group, sulle corrispondenti righe corrispondenti in DT1, calcoliamo l'espressione .N >= 2L; specificando by = .EACHI (controllare 1.9.4 NEWS), calcoliamo l'espressione j ogni volta.


In 1.9.4, .() è stata introdotta come alias in ciascuno i, j e by. Così si potrebbe anche fare:

DT1[.(DT2$group), .(popular = .N >= 2L), by = .EACHI] 

Quando si sta unendo da una colonna singolo carattere, è possibile eliminare la sintassi .()/J() del tutto (per comodità). Quindi questo può anche essere scritto come:

DT1[DT2$group, .(popular = .N >= 2L), by = .EACHI] 
+1

Professional data-tabler –

+0

Che sia pura magia. Devi aggiungere alcune informazioni per i futuri lettori –

+2

@DavidArenburg, fatto. – Arun

3

Questo è come lo farei questo: per prima cosa conta il numero di volte in cui ogni gruppo appare in DT1, quindi semplicemente unire DT2 e DT1.

require(data.table) 
DT1 <- data.table(num = 1:6, group = c("A", "B", "B", "B", "A", "C")) 
DT2 <- data.table(group = c("A", "B", "C")) 

#solution: 
DT1[,num_counts:=.N,by=group] #the number of entries in this group, just count the other column 
setkey(DT1, group) 
setkey(DT2, group) 
DT2 = DT1[DT2,mult="last"][,list(group, popular = (num_counts >= 2))] 

#> DT2 
# group popular 
#1:  A TRUE 
#2:  B TRUE 
#3:  C FALSE 
+0

concordato, modificato la soluzione – Alex

+0

Questo può essere ulteriormente semplificato aggregando' DT1' invece di 'aggiornarlo'. – Arun

+0

penso che l'aggiornamento sia più efficiente: l'aggregazione implicherebbe la copia mentre l'aggiornamento non richiede alcuna copia – Alex