2016-04-29 15 views
12

Ho un largish data.table con due colonne, id e var:combinazioni COUNT di lunghezza 2 per id

head(DT) 
# id var 
# 1: 1 B 
# 2: 1 C 
# 3: 1 A 
# 4: 1 C 
# 5: 2 B 
# 6: 2 C 

Vorrei creare una sorta di tavola incrociata che mostra quante volte differente lunghezza 2 -combinazioni di var si sono verificati nei dati.

attesi uscita per i dati di esempio:

out 
# A B C 
# A 0 3 3 
# B NA 1 3 
# C NA NA 0 

Spiegazione:

  • la diagonale del conseguente Matrix/data.frame/conta data.table quante volte tutto var s che si è verificato per un id erano tutti uguali (o tutti i A o B o C). Nei dati di esempio, id 4 ha una sola voce e cioè B, quindi B - B è 1 nel risultato desiderato.
  • triangolo superiore conta per quante id s due specifici var s erano presenti, cioè la combinazione A - B è presente in 3 id s, come sono combinazioni A - C e B - C.
  • Si noti che per qualsiasi id, una singola combinazione di due var s può essere solo 0 (non presente) o 1 (presente), vale a dire non voglio contarlo più volte per id.
  • il triangolo inferiore del risultato può essere lasciato NA o 0 oppure potrebbe avere gli stessi valori del triangolo superiore, ma sarebbe ridondante.

(Il risultato potrebbe anche essere somministrato in-formato lungo finché è presente le informazioni pertinenti.)

sono sicuro che ci sia un modo intelligente (efficiente) del calcolo di tale, ma posso' attualmente mi avvolgo la testa.

dati del campione:

DT <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L), var = c("B", "C", "A", 
"C", "B", "C", "C", "A", "B", "B", "C", "C", "C", "C", "B", "C", 
"B", "A", "C", "B")), .Names = c("id", "var"), row.names = c(NA, 
-20L), class = "data.frame") 

library(data.table) 
setDT(DT, key = "id") 
+0

Quanto grande è abbastanza grande? – Heroka

+0

@Heroka qualche milione di file al momento, diciamo 3. –

risposta

10

Dal momento che siete ok con risultati a lungo forma:

DT[, if(all(var == var[1])) 
     .(var[1], var[1]) 
    else 
     as.data.table(t(combn(sort(unique(var)), 2))), by = id][ 
    , .N, by = .(V1, V2)] 
# V1 V2 N 
#1: A B 3 
#2: A C 3 
#3: B C 3 
#4: B B 1 

O se chiamiamo l'output sopra res:

dcast(res[CJ(c(V1,V2), c(V1,V2), unique = T), on = c('V1', 'V2')][ 
      V1 == V2 & is.na(N), N := 0], V1 ~ V2) 
# V1 A B C 
#1: A 0 3 3 
#2: B NA 1 3 
#3: C NA NA 0 

.210

Un'alternativa a combn sta facendo:

DT[, if (all(var == var[1])) 
     .(var[1], var[1]) 
    else 
     CJ(var, var, unique = T)[V1 < V2], by = id][ 
    , .N, by = .(V1, V2)] 
# V1 V2 N 
# 1: A B 3 
# 2: A C 3 
# 3: B C 3 
# 4: B B 1 

# or combn with list output (instead of matrix) 

unique(DT, by=NULL)[ order(var), if(.N==1L) 
     .(var, var) 
    else 
     transpose(combn(var, 2, simplify=FALSE)), by = id][ 
    , .N, by = .(V1, V2)] 
+0

Bello! Stavo pensando in questo modo. Tuttavia, nel caso di più vars identici (come solo 'B' s per l'ID 5, ma quattro di essi), si otterrebbe un errore n Heroka

+0

@Heroka buon punto - fisso – eddi

+0

Grazie eddi! Dovrò investigare un po '(+1) –

Problemi correlati