¿Cómo calculo la coincidencia en la tabla?

Tengo una matriz simple, por ejemplo

test <- matrix(c("u1","p1","u1","p2","u2","p2","u2", "p3","u3","p1","u4","p2","u5","p1", "u5","p3","u6","p3","u7","p4","u7", "p3","u8","p1","u9","p4"), ncol=2,byrow=TRUE) colnames(test) <- c("user","product") test1<-as.data.frame(test) 

prueba:

  user product 1 u1 p1 2 u1 p2 3 u2 p2 4 u2 p3 5 u3 p1 6 u4 p2 7 u5 p1 8 u5 p3 9 u6 p3 10 u7 p4 11 u7 p3 12 u8 p1 13 u9 p4 

Quiero contar cuántos usuarios compraron un par de productos juntos, como p1 y p2, p2 y p3 …

table(test1$product,test1$product) dame esto:

  p1 p2 p3 p4 p1 4 0 0 0 p2 0 3 0 0 p3 0 0 4 0 p4 0 0 0 2 

¿Cómo puedo obtener el resultado correcto como:

  p1 p2 p3 p4 p1 4 1 1 0 p2 1 3 1 0 p3 1 1 4 1 p4 0 0 1 2 

En cuanto a la salida deseada, está buscando la función crossprod :

 crossprod(table(test1)) # product # product p1 p2 p3 p4 # p1 4 1 1 0 # p2 1 3 1 0 # p3 1 1 4 1 # p4 0 0 1 2 

Esto es lo mismo que crossprod(table(test1$user, test1$product)) (que refleja el comentario de Dennis).

La solución de Ananda es superior (es más liviana y no requiere paquete externo) pero estoy bajando otra. Creo que esto se llama una matriz de adyacencia (las personas más inteligentes se sienten libres de editar esto si estoy equivocado):

 library(qdap) adjmat(table(test1))$adjacency ## product ## product p1 p2 p3 p4 ## p1 4 1 1 0 ## p2 1 3 1 0 ## p3 1 1 4 1 ## p4 0 0 1 2 

Una pregunta similar etiquetada en esta publicación solicitó una solución eficiente, pero se eliminó la eliminación ahora. Decidimos publicar la solución aquí.

Aquí hay uno con RcppEigen para hacer el producto cruzado

 library(RcppEigen) library(inline) prodFun < - ' typedef Eigen::Map MapMti; const MapMti B(as(BB)); const MapMti C(as(CC)); return List::create(B.adjoint() * C); ' funCPr < - cxxfunction(signature(BB= "matrix", CC = "matrix"), prodFun, plugin = "RcppEigen") tbl <- table(test1) funCPr(tbl, tbl)[[1]] # [,1] [,2] [,3] [,4] #[1,] 4 1 1 0 #[2,] 1 3 1 0 #[3,] 1 1 4 1 #[4,] 0 0 1 2 

Puntos de referencia

 set.seed(24) test2 < - data.frame(user = sample(1:5000, 1e6, replace=TRUE), product = sample(paste0("p", 1:50), 1e6, replace = TRUE), stringsAsFactors=FALSE) tbl1 <- table(test2) library(microbenchmark) microbenchmark(cPP = funCPr(tbl1, tbl1)[[1]], CrossP = crossprod(tbl1), adjMat = adjmat(tbl1)$adjacency, unit = "relative", times = 10L) #Unit: relative # expr min lq mean median uq max neval cld # cPP 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 10 a # CrossP 2.079867 2.070509 2.234376 2.074388 2.290516 2.676798 10 a # adjMat 6.223034 6.500791 9.619088 7.197824 7.771270 31.394812 10 b 

NOTA: Esto podría hacerse más eficiente haciendo la table en Rcpp