Análisis Algoritmo Apriori

Carlos Andrés Gómez

marzo 2023

Los algoritmos de reglas de asociación representan una técnica dentro de la minería de datos, teniendo como objetivo encontrar patrones de relaciones dentro un conjunto de transacciones.
El Algoritmo Apriori, está diseñado para operar sobre bases de datos que contienen transacciones (por ejemplo, colecciones de artículos comprados por consumidores) en donde cada transacción es vista como un conjunto de ítems y es uno de los más utilizados para crear sistemas de recomendaciones que vemos en muchos sitios web.

Obtención de los datos a analizar

Los datos para este ejemplo son descargados desde un repositorio de Github y se encuentran en formato CSV. Se comprueba la url y se descarga automaticamente el documento en el repositorio local creado.

filedata <- "https://raw.githubusercontent.com/rociochavezmx/Rocio-Chavez-youtube-Files/master/Datos%20Compras.csv"

if(!file.exists("DatosCompras.csv")){
     download.file(filedata, destfile = "DatosCompras.csv")
}

Se lee el archivo a analizar

Se lee el archivo descargado en formato CSV y se procede a transformar la variable producto en una variable categórica.

datos_Apriori <- read.csv("DatosCompras.csv", sep = ",", dec = ".", header = TRUE)

datos_Apriori <- datos_Apriori %>% mutate(Producto = as.factor(Producto))

Selección de registros completos

Para procesar los datos de la forma correcta, se realiza un filtrado de tales con el fin de eliminar datos faltantes u errores en la base de datos, para ello usamos la función de R complete.cases

datos_Apriori1 <- datos_Apriori[complete.cases(datos_Apriori), ]

Creación de subset de datos para las transacciones

Se organizan los datos de manera que cada transacción (venta) se represente en una única fila y los artículos estén separados por coma (,) para lograr el formato deseado para el análisis.

transacciones <- ddply(datos_Apriori1,c("Transaccion"),
                       function(df1)paste(df1$Producto,
                                          collapse = ","))

transacciones$Transaccion <- NULL

Se guarda la DB transformada como CSV

write.csv(transacciones,"transacciones.csv", quote = FALSE, row.names = FALSE)
tr <- read.transactions("transacciones.csv", format = 'basket', sep=',', header = TRUE)

Desplegamos las transacciones en consola

inspect(tr)
##      items                                        
## [1]  {Huevos, Leche, Mantequilla, Pan}            
## [2]  {Catsup, Harina, Leche, Salchichas}          
## [3]  {Catsup, Mantequilla, Mermerlada, Salchichas}
## [4]  {Leche, Mantequilla, Pan}                    
## [5]  {Galletas, Mantequilla, Pan}                 
## [6]  {Galletas, Leche, Mantequilla, Pan}          
## [7]  {Galletas, Leche}                            
## [8]  {Leche, Mantequilla, Pan}                    
## [9]  {Galletas, Huevos, Mantequilla, Pan}         
## [10] {Leche, Mantequilla, Pan}                    
## [11] {Leche, Mantequilla, Pan}                    
## [12] {Atun, Catsup, Galletas, Leche, Pan}

Productos más vendidos

En esta gráfica se presentan los 10 productos que más se han vendido y se muestran por frecuencia absoluta.

itemFrequencyPlot(tr, topN = 10, type = 'absolute')

**Aplicación del algoritmo Apriori para hallar las reglas de asociación

Las Reglas de Asociación nos dice que si un cliente compra, un producto “X”, qué tan probable es que compre otro, donde estos dos productos están relacionados porque otros clientes los compraron a ambos.

reglas_asociacion <- apriori(tr, parameter = list(supp=0.1, conf=0.7, minlen=2))
## Apriori
## 
## Parameter specification:
##  confidence minval smax arem  aval originalSupport maxtime support minlen
##         0.7    0.1    1 none FALSE            TRUE       5     0.1      2
##  maxlen target  ext
##      10  rules TRUE
## 
## Algorithmic control:
##  filter tree heap memopt load sort verbose
##     0.1 TRUE TRUE  FALSE TRUE    2    TRUE
## 
## Absolute minimum support count: 1 
## 
## set item appearances ...[0 item(s)] done [0.00s].
## set transactions ...[10 item(s), 12 transaction(s)] done [0.00s].
## sorting and recoding items ... [7 item(s)] done [0.00s].
## creating transaction tree ... done [0.00s].
## checking subsets of size 1 2 3 done [0.00s].
## writing ... [15 rule(s)] done [0.00s].
## creating S4 object  ... done [0.00s].

Se organizan las reglas en orden descendente

reglas_asociacion <- sort(reglas_asociacion, by = "confidence", decreasing = TRUE)

Se muestran las reglas de asociación creadas a partir del algoritmo Apriori

#inspect(reglas_asociacion)
inspectDT(reglas_asociacion[1:12])

Se revisa si existen reglas duplicadas

duplicated(reglas_asociacion)
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE

Se verifica si existen reglas redundantes

Dos reglas son identicas si tienen el mismo antecedente y consecuente. Una regla es redundante si existe otra regla con un consecuente igual y cuyo antecedente sea un subconjunto de los productos que tiene en su antecedente.

La regla que tiene más productos siempre tiene un soporte menor y se considera redundante ya que no aporta información adicional.

reglas_redundantes <- is.redundant(reglas_asociacion)

Se muestran las reglas que son redundantes

which(is.redundant(reglas_asociacion))
## [1]  4  5 10 14 15

Se eliminan las reglas que son redundantes

Se eliminan las reglas que son redundantes y nos quedamos con las reglas que realmente aportan información.

reglas_podadas <- reglas_asociacion[!reglas_redundantes]

Se muestran las reglas podadas

inspect(reglas_podadas, by = "confidence")
##      lhs                        rhs           support   confidence coverage 
## [1]  {Huevos}                => {Mantequilla} 0.1666667 1.0000000  0.1666667
## [2]  {Huevos}                => {Pan}         0.1666667 1.0000000  0.1666667
## [3]  {Salchichas}            => {Catsup}      0.1666667 1.0000000  0.1666667
## [4]  {Galletas, Mantequilla} => {Pan}         0.2500000 1.0000000  0.2500000
## [5]  {Leche, Mantequilla}    => {Pan}         0.5000000 1.0000000  0.5000000
## [6]  {Mantequilla}           => {Pan}         0.6666667 0.8888889  0.7500000
## [7]  {Pan}                   => {Mantequilla} 0.6666667 0.8888889  0.7500000
## [8]  {Galletas}              => {Pan}         0.3333333 0.8000000  0.4166667
## [9]  {Leche}                 => {Pan}         0.5833333 0.7777778  0.7500000
## [10] {Pan}                   => {Leche}       0.5833333 0.7777778  0.7500000
##      lift     count
## [1]  1.333333 2    
## [2]  1.333333 2    
## [3]  4.000000 2    
## [4]  1.333333 3    
## [5]  1.333333 6    
## [6]  1.185185 8    
## [7]  1.185185 8    
## [8]  1.066667 4    
## [9]  1.037037 7    
## [10] 1.037037 7

Red de Reglas de asociación con el algoritmo Apriori

plot(reglas_podadas, method = "graph",  engine = "htmlwidget", shading = "confidence")

Se agregan los indicadores Leverage y Conviction

quality(reglas_podadas) <- cbind(quality(reglas_podadas), leverage = interestMeasure(reglas_podadas, measure = "leverage", transactions = tr), conviction = interestMeasure(reglas_podadas, measure = "conviction", transactions = tr))

inspect(reglas_podadas, by = "confidence")
##      lhs                        rhs           support   confidence coverage 
## [1]  {Huevos}                => {Mantequilla} 0.1666667 1.0000000  0.1666667
## [2]  {Huevos}                => {Pan}         0.1666667 1.0000000  0.1666667
## [3]  {Salchichas}            => {Catsup}      0.1666667 1.0000000  0.1666667
## [4]  {Galletas, Mantequilla} => {Pan}         0.2500000 1.0000000  0.2500000
## [5]  {Leche, Mantequilla}    => {Pan}         0.5000000 1.0000000  0.5000000
## [6]  {Mantequilla}           => {Pan}         0.6666667 0.8888889  0.7500000
## [7]  {Pan}                   => {Mantequilla} 0.6666667 0.8888889  0.7500000
## [8]  {Galletas}              => {Pan}         0.3333333 0.8000000  0.4166667
## [9]  {Leche}                 => {Pan}         0.5833333 0.7777778  0.7500000
## [10] {Pan}                   => {Leche}       0.5833333 0.7777778  0.7500000
##      lift     count leverage   conviction
## [1]  1.333333 2     0.04166667   Inf     
## [2]  1.333333 2     0.04166667   Inf     
## [3]  4.000000 2     0.12500000   Inf     
## [4]  1.333333 3     0.06250000   Inf     
## [5]  1.333333 6     0.12500000   Inf     
## [6]  1.185185 8     0.10416667 2.250     
## [7]  1.185185 8     0.10416667 2.250     
## [8]  1.066667 4     0.02083333 1.250     
## [9]  1.037037 7     0.02083333 1.125     
## [10] 1.037037 7     0.02083333 1.125

Se preparan y se guardan las reglas para ser almacenadas

Se preparan los datos en formato dataframe y se guardan en formato CSV de manera que el cliente pueda observar fácilmente las reglas construidas y a partir de estos resultados aplicar las medidas que considere.

productos_frecuentes <- data.frame(Productos = labels(reglas_podadas), 
                                  Indicador = reglas_podadas@quality)


write.csv(productos_frecuentes, "productos_frecuentes.csv")