Creando una matriz de co-ocurrencia

Estoy tratando de resolver el problema de tener una matriz de co-ocurrencia. Tengo un archivo de datos de transacciones y artículos, y quiero ver una matriz de la cantidad de transacciones donde los artículos aparecen juntos.

Soy un novato en la progtwigción de R y me divierto descubriendo todos los atajos que tiene R, en lugar de crear bucles específicos (solía usar C hace años y ahora solo me apegaba a las macros de Excel y a SPSS). He comprobado las soluciones aquí, pero no he encontrado una que funcione (la más cercana es la solución dada aquí: ¿ matriz de coincidencia usando SAC? – pero produjo un mensaje de error cuando utilicé projecting_tm, sospeché que el cbind wasn ‘ t exitoso en mi caso.

Básicamente, tengo una tabla que contiene lo siguiente:

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. 

Quiero crear 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 

Lo que hice fue (y probablemente te reirías de mi aproximación R novata):

 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 se mencionó anteriormente, el cbind probablemente no tuvo éxito, por lo que projecting_tm no pudo darme ningún resultado.

¿Algún enfoque alternativo o una corrección a mi método?

¡Tu ayuda sería muy apreciada!

Utilizaría una combinación del paquete reshape2 y el á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 la graficación tal vez ...

 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 cualquiera de las respuestas anteriores, pruebe con crossprod y la 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 razones de eficiencia, especialmente en datos dispersos, recomendaría usar una matriz dispersa.

 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 

Estaba probando cada solución publicada en este hilo. Ninguno de ellos funcionaba con matrices grandes (estaba trabajando con una matriz de 1.500 x 2.000.000).

Un poco fuera de tema : después de calcular una matriz de co-ocurrencias, generalmente quiero calcular la distancia entre los elementos individuales. La similitud / distancia del coseno se puede calcular de manera eficiente en la matriz de co-ocurrencia 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 

Yo usaría xtabs para esto:

 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 

Lancé el sparse = TRUE para mostrar que esto puede funcionar para conjuntos de datos muy grandes.

Esto es realmente muy fácil y limpio si primero crea un gráfico bipartito, donde los nodos superiores son las transacciones y los nodos inferiores son los elementos. Luego creas una proyección en los nodos 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