2015-10-06 20 views
6

Ho dati che mostrano quali clienti hanno acquistato determinati articoli. Possono acquistare un oggetto più volte. Quello di cui ho bisogno è una tabella che mostri tutte le possibili combinazioni di articoli a coppie insieme al numero unico di clienti che hanno acquistato quella combinazione (la diagonale del tavolo sarà solo il numero univoco di persone che acquistano ciascun articolo).Crea tabella con tutte le coppie di valori da una colonna in R, contando valori univoci

Ecco un esempio:

item <- c("h","h","h","j","j") 
customer <- c("a","a","b","b","b") 
test.data <- data.frame(item,customer) 

Ecco la test.data:

item customer 
h a 
h a 
h b 
j b 
j b 

Risultato necessario - una tabella con gli articoli come nomi di riga e di colonna, con i conti di clienti unici acquistando la coppia all'interno del tavolo. Quindi, 2 clienti hanno acquistato l'articolo h, 1 hanno acquistato entrambi gli articoli h e j e 1 l'elemento acquistato j.

item h j 
h  2 1 
j  1 1 

Ho provato con la funzione di tabella, melt/cast, ecc, ma nulla mi fa i conteggi di cui ho bisogno all'interno della tabella. Il mio primo passo è utilizzare unique() per sbarazzarsi di righe duplicate.

+2

si parla di 3 clienti, ma vedo solo 2 nel vostro 'test. data'. – Jaap

+0

Non sarà possibile estenderlo oltre due elementi. Forse dovresti considerare un altro modo di rappresentarlo. – Frank

+0

@Jaap, il cliente b ha acquistato entrambi gli articoli h e j, quindi sono inclusi in tutte e quattro le combinazioni (nella tabella si legge "2 clienti che hanno acquistato anche h acquistati", "1 cliente che ha acquistato anche acquistato j" e "1 il cliente che ha acquistato j ha anche acquistato j "- sì, le interpretazioni del valore diagonale sono strane, ma è quello che mi serve. – user1228982

risposta

5

Utilizzando data.table e il pacchetto gtools, siamo in grado di ricreare tutte le possibili permutazioni dal cliente:

library(data.table) 
library(gtools) 

item <- c("h","h","h","j","j") 
customer <- c("a","a","b","b","b") 
test.data <- data.table(item,customer) 

DT <- unique(test.data) #The unique is used as multiple purchases do not count twice 

tuples <- function(x){ 
    return(data.frame(permutations(length(x), 2, x, repeats.allowed = T, set = F), stringsAsFactors = F)) 
} 

DO <- DT[, tuples(item), by = customer] 

Questo dà:

customer X1 X2 
1:  a h h 
2:  b h h 
3:  b h j 
4:  b j h 
5:  b j j 

che è un elenco di tutte le associazioni elemento univoco un cliente ha. Come per il tuo esempio stiamo trattando h x j in modo diverso da j x h. Ora possiamo ottenere la frequenza di ogni coppia utilizzando la funzione di tabella:

table(DO$X1,DO$X2) 
    j h 
    j 1 1 
    h 1 2 
+0

@ Chris, grazie per la risposta. Questo funziona benissimo per il piccolo esempio che ho fornito, tuttavia ci sono milioni di righe nel set di dati originale (anche se meno di 100 oggetti unici), quindi non sono sicuro di quanto questo sarà scalabile! – user1228982

+0

@ user1228982 con 100 clienti, 100 prodotti e 1.000.000 di righe, viene eseguito in meno di un secondo sul mio computer.Prova usando 'item <- sample (1: 100,1000000, replace = T)' 'customer <- sample (1: 100,1000000, replace = T)' – Chris

+0

@ user1228982 sebbene sia più lento della soluzione di Frank – Chris

5

Ecco una soluzione di base R:

n_intersect <- Vectorize(function(x,y) length(intersect(x,y))) 

cs_by_item <- with(test.data, tapply(customer, item, unique)) 

outer(cs_by_item , cs_by_item , n_intersect) 
# h j 
# h 2 1 
# j 1 1 
+0

La tua soluzione ha funzionato benissimo per un set di dati più piccolo, tuttavia quando ho provato a utilizzarlo con i miei dati completi, non è mai terminato. – user1228982

+0

@ user1228982 Sì, non sono sorpreso. La funzione 'outer' ha spesso problemi del genere, consumando molta memoria. – Frank

Problemi correlati