Criando matriz de co-ocorrência

Estou tentando resolver o problema de ter uma matriz de co-ocorrência. Eu tenho um arquivo de dados de transactions e itens, e eu quero ver uma matriz do número de transactions onde os itens aparecem juntos.

Sou novato em programação em R e estou me divertindo descobrindo todos os atalhos que o R tem, em vez de criar loops específicos (eu costumava usar o C anos atrás e só aderir às macros do Excel e ao SPSS agora). Eu verifiquei as soluções aqui, mas não encontrei uma que funcionasse (o mais próximo é a solução dada aqui: matriz de coocorrência usando SAC? – mas produziu uma mensagem de erro quando eu usei projecting_tm, eu suspeitei que o cbind não era t bem sucedido no meu caso.

Essencialmente eu tenho uma tabela contendo o seguinte:

TrxID Items Quant Trx1 A 3 Trx1 B 1 Trx1 C 1 Trx2 E 3 Trx2 B 1 Trx3 B 1 Trx3 C 4 Trx4 D 1 Trx4 E 1 Trx4 A 1 Trx5 F 5 Trx5 B 3 Trx5 C 2 Trx5 D 1, etc. 

Eu quero criar algo como:

  ABCDEF A 0 1 1 0 1 1 B 1 0 3 1 1 0 C 1 3 0 1 0 0 D 1 1 1 0 1 1 E 1 1 0 1 0 0 F 0 1 1 1 0 0 

O que eu fiz foi (e você provavelmente riria da minha abordagem R de novato):

 library(igraph) library(tnet) trx <- read.table("FileName.txt", header=TRUE) transID <- t(trx[1]) items <- t(trx[2]) id_item <- cbind(items,transID) item_item <- projecting_tm(id_item, method="sum") item_item <- tnet_igraph(item_item,type="weighted one-mode tnet") item_matrix <-get.adjacency(item_item,attr="weight") item_matrix 

Como mencionado acima, o cbind provavelmente não teve sucesso, então o projecting_tm não poderia me dar nenhum resultado.

Qualquer abordagem alternativa ou uma correção ao meu método?

Sua ajuda será muito apreciada!

   

Eu usaria uma combinação do pacote reshape2 e da álgebra matricial:

 #read in your data dat < - read.table(text="TrxID Items Quant Trx1 A 3 Trx1 B 1 Trx1 C 1 Trx2 E 3 Trx2 B 1 Trx3 B 1 Trx3 C 4 Trx4 D 1 Trx4 E 1 Trx4 A 1 Trx5 F 5 Trx5 B 3 Trx5 C 2 Trx5 D 1", header=T) #making the boolean matrix library(reshape2) dat2 <- melt(dat) w <- dcast(dat2, Items~TrxID) x <- as.matrix(w[,-1]) x[is.na(x)] <- 0 x <- apply(x, 2, function(x) as.numeric(x > 0)) #recode as 0/1 v < - x %*% t(x) #the magic matrix diag(v) <- 0 #repalce diagonal dimnames(v) <- list(w[, 1], w[,1]) #name the dimensions v 

Para o gráfico talvez ...

 g < - graph.adjacency(v, weighted=TRUE, mode ='undirected') g <- simplify(g) # set labels and degrees of vertices V(g)$label <- V(g)$name V(g)$degree <- degree(g) plot(g) 

Usando “dat” de qualquer uma das respostas acima, tente crossprod e table :

 V < - crossprod(table(dat[1:2])) diag(V) <- 0 V # Items # Items ABCDEF # A 0 1 1 1 1 0 # B 1 0 3 1 1 1 # C 1 3 0 1 0 1 # D 1 1 1 0 1 1 # E 1 1 0 1 0 0 # F 0 1 1 1 0 0 

Por motivos de eficiência, especialmente em dados esparsos, recomendo usar uma matriz esparsa.

 dat < - read.table(text="TrxID Items Quant Trx1 A 3 Trx1 B 1 Trx1 C 1 Trx2 E 3 Trx2 B 1 Trx3 B 1 Trx3 C 4 Trx4 D 1 Trx4 E 1 Trx4 A 1 Trx5 F 5 Trx5 B 3 Trx5 C 2 Trx5 D 1", header=T) library("Matrix") # factors for indexing matrix entries and naming dimensions trx.fac <- factor(dat[,1]) itm.fac <- factor(dat[,2]) s <- sparseMatrix( as.numeric(trx.fac), as.numeric(itm.fac), dimnames = list( as.character(levels(trx.fac)), as.character(levels(itm.fac))), x = 1) # calculating co-occurrences v <- t(s) %*% s # setting transactions counts of items to zero diag(v) <- 0 v 

Eu estava dando a cada solução postada neste tópico uma tentativa. Nenhum deles trabalhava com grandes matrizes (eu estava trabalhando com uma matriz de 1.500 x 2.000.000).

Um pouco fora do tópico : depois de calcular uma matriz de co-ocorrência, eu normalmente quero calcular a distância entre itens individuais. A similaridade / distância do cosseno pode ser calculada eficientemente na matriz de co-ocorrência como esta:

 # cross-product of vectors (numerator) num < - v %*% v # square root of square sum of each vector (used for denominator) srss <- sqrt(apply(v^2, 1, sum)) # denominator den <- srss %*% t(srss) # cosine similarity v.cos.sim <- num / den # cosine distance v.cos.dist <- 1 - v.cos.sim 

Eu usaria o xtabs para isso:

 dat < - read.table(text="TrxID Items Quant Trx1 A 3 Trx1 B 1 Trx1 C 1 Trx2 E 3 Trx2 B 1 Trx3 B 1 Trx3 C 4 Trx4 D 1 Trx4 E 1 Trx4 A 1 Trx5 F 5 Trx5 B 3 Trx5 C 2 Trx5 D 1", header=T) term_doc <- xtabs(~ TrxID + Items, data=dat, sparse = TRUE) co_occur <- crossprod(term_doc, term_doc) diag(co_occur) <- 0 co_occur 

Eu joguei no sparse = TRUE para mostrar que isso pode funcionar para conjuntos de dados muito grandes.

Isso é realmente muito fácil e limpo se você criar um gráfico bipartido primeiro, onde os nós principais são as transactions e os nós inferiores são os itens. Então você cria uma projeção para os nós inferiores.

 dat < - read.table(text="TrxID Items Quant Trx1 A 3 Trx1 B 1 Trx1 C 1 Trx2 E 3 Trx2 B 1 Trx3 B 1 Trx3 C 4 Trx4 D 1 Trx4 E 1 Trx4 A 1 Trx5 F 5 Trx5 B 3 Trx5 C 2 Trx5 D 1", header=T) library(igraph) bip <- graph.data.frame(dat) V(bip)$type <- V(bip)$name %in% dat[,1] ## sparse=TRUE is a good idea if you have a large matrix here v <- get.adjacency(bipartite.projection(bip)[[2]], attr="weight", sparse=FALSE) ## Need to reorder if you want it alphabetically v[order(rownames(v)), order(colnames(v))] # ABCDEF # A 0 1 1 1 1 0 # B 1 0 3 1 1 1 # C 1 3 0 1 0 1 # D 1 1 1 0 1 1 # E 1 1 0 1 0 0 # F 0 1 1 1 0 0