La minería de reglas de asociación se emplea para descubrir patrones de objetos o atributos que suelen ocurrir juntos, a partir del estudio de bases de datos transaccionales. Concretamente, una regla de asociación es una implicación de la forma \(\small{X \implies Y}\), donde \(\small{X}\) e \(\small{Y}\) son dos conjuntos disjuntos de items. Esto significa que si encontramos todos los items en \(\small{X}\) en una transacción, esperamos encontrar también los items en \(\small{Y}\) (con una determinada confianza). Esto nos permite establecer relaciones entre variables cualitativas. Importante destacar que esta relación implica coocurrencia, no causalida.
Entre las aplicaciones donde las reglas de asociación pueden ser útiles, encontramos:
Análisis de la cesta de la compra: asociación entre artículos comprados. Por ejemplo, una regla de tipo {pan} \(\small{\implies}\) {leche} implica que es muy frecuente la compra de pan y leche juntos.
Análisis de textos
Identificación de patrones en páginas web: análisis de consultas para adaptar la interfaz a la actividad del usuario.
Bioinformática y diagnóstico médico
Una transacción puede equivaler, pues, a una cesta dela compra, un usuario, una sesión de usuario en la web, etc.
Items: artículos que componen una transacción
Itemset: conjunto de items de una transacción. Un \(\small{k}\)-itemset es un itemset con \(\small{k}\) artículos. Ej.: productos de la cesta de la compra, páginas web visitadas, etc.
Base de datos transaccional: conjunto de transacciones (\(\small{T = }\) {\(\small{t_1, t_2, ..., t_N}\)}). Cada transacción viene representada por su conjunto de items (\(\small{I = }\) {\(\small{i_1, i_2, ..., i_d}\)})
Dos de las formas en las que podemos ver representada una base de datos transaccional son:
Disposición horizontal o tipo basket, donde se representan un conjunto de artículos por fila:
TID | items |
---|---|
1 | {leche, cerveza} |
2 | {leche, pan, huevos} |
3 | {pan, servilletas} |
4 | {leche, pan, huevos, servilletas} |
Disposición vertical, con artículo por columna:
leche | cerveza | pan | huevos | servilletas |
---|---|---|---|---|
1 | 1 | 1 | 1 | 3 |
2 | 2 | 3 | 5 | |
3 | 4 | |||
4 | 5 |
Representación binaria (1 = artículo presente, 0 = artículo ausente):
TID | leche | cerveza | pan | huevos | servilletas |
---|---|---|---|---|---|
1 | 1 | 1 | 0 | 0 | 0 |
2 | 1 | 0 | 1 | 1 | 0 |
3 | 0 | 0 | 1 | 0 | 1 |
4 | 1 | 0 | 1 | 1 | 1 |
El soporte y la confianza son dos parámetros importantes en los algoritmos basados en reglas. Sea \(\small{X}\) un itemset, su soporte es la fracción de transacciones que lo incluyen:
donde \(\small{N}\) es el número de transacciones de la base de datos, y \(\small{count(X ∪ Y)}\) el número de transacciones que contienen todos los items en \(\small{X}\) (antecedente) o \(\small{Y}\) (consecuente).
Siguiendo los ejemplos anteriores, el soporte de cada itemset sería:
itemset | Soporte |
---|---|
{leche, servilletas} | 1/4 |
{leche, pan} | 2/4 |
{pan, servilletas} | 1/4 |
{huevos, servilletas} | 1/4 |
Por otro lado, la confianza de una regla se define como la fracción de transacciones en las que aparecen los itemsets \(\small{X}\) e \(\small{Y}\):
También puede interpretarse como lo frecuente que es que una transacción que contiene el itemset \(\small{X}\) también contenga el itemset \(\small{Y}\).
A continuación se ejemplifica el cálculo de ambos en base al ejemplo:
TID | items |
---|---|
1 | {leche, cerveza} |
2 | {leche, pan, huevos} |
3 | {pan, servilletas} |
4 | {leche, pan, huevos, servilletas} |
El soporte de la regla {leche, pan} \(\small{\implies}\) {huevos} sería:
Para el cálculo de la confianza, necesitamos además el cálculo de la confianza de \(\small{X}\):
\(\small{soporte(X)}\) = soporte({leche, pan}) = 2/4
\(\small{conf(X \implies Y) = \frac{2/4}{2/4}}\) = 1Para descubrir reglas de asociación, es necesario establecer unos límites mínimos de sorporte y confianza. Así, un itemset frecuente será aquel itemset cuyo soporte supere un mínimo establecido.
El proceso de búsqueda de reglas de asociación consistirá en dos pasos:
Detectar itemsets frecuentes que superen un soporte mínimo, es decir, cuya ocurrencia supera un mínimo de transacciones
Obtener las reglas de asociación asociadas a dichos itemsets que superen una determinada confianza
Uno de los algoritmos que permiten generar reglas de asociación a partir de itemsets frecuentes es el algoritmo Apriori. El principio Apriori establece que todos los subconjuntos no vacíos de un itemset frecuentes, también son frecuentes. Por ejemplo, si el itemset {b, c} es frecuente, puedo suponer por ejemplo que {b} es también frecuente (como mínimo aparecerá el mismo número de veces que {b, c}). De igual forma, cualquier adición de items a {b, c} también será frecuente:
Por otro lado, si {c, d} es infrecuente, {b, c, d} tampoco será frecuente. Esta propiedad se conoce como antimonotonicidad, y permite hacer una poda en el espacio de búsqueda basada en el soporte:
El algoritmo Apriori genera itemsets frecuentes en base a los siguientes pasos:
Siendo \(\small{C_k}\) el conjunto de \(\small{k}\)-itemsets candidatos y \(\small{F_k}\) el conjunto de itemsets frecuentes, el algoritmo comienza obteniendo los itemsets frecuentes de tamaño 1 (1-itemsets). De forma iterativa, se continúan generando \(\small{k}\)-itemsets candidatos a partir de los frecuentes de tamaño anterior (\(\small{k-1}\)), generando nuevas combinaciones añadiendo items frecuentes. De estos nuevos candidatos se vuelven a determinar los que son frecuentes, mediante el cálculo del soporte (los que son frecuentes se mantienen, y los que no superan el soporte mínimo se “podan” o descartan, manteniendo la propiedad de antimonotonicidad). Del conjunto \(\small{C_k}\) se selecciona el subconjunto \(\small{F_k}\). El proceso termina cuando ya no se generan más \(\small{k}\)-itemsets frecuentes.
Entre las estrategias para la generación de candidatos se encuentran:
Fuerza bruta: se consideran todos los \(\small{k}\)-itemsets posibles como candidatos, donde el número de posibles candidatos es \(\small{\begin{pmatrix}d \\k\end{pmatrix}}\), donde \(\small{d}\) es el número de items. El proceso de poda es muy costoso.
Método \(\small{F_{k-1} × F_1}\): se basa en extender cada \(\small{k-1}\)-itemset frecuente con un 1-itemset frecuente. El número de posibles candidatos será de \(\small{O(|F_{k-1}||F_1|)}\). Podemos ver un ejemplo en la siguiente imagen:
Se comienza calculando el soporte de los itemsets candidatos de tamaño 1 (\(\small{C_1}\)). Se eliminan los 1-itemsets que no superen el soporte mínimo establecido, y se mantiene el conjunto más frecuente \(\small{F_1}\). Se sigue el proceso generando las posibles las combinaciones de tamaño 2 (\(\small{C_2}\)) a partir de los frecuentes de tamaño 1. De nuevo se eliminan los 2-itemsets generados que no lleguen a un soporte mínimo, obteniéndose el conjunto \(\small{F_2}\). Se continúa hasta alcanzar el conjunto frecuente de tamaño 3 (\(\small{F_3}\)).
Una vez vistos estos métodos, podemos introducir nuevas definiciones:
Itemset maximal frecuente: itemsets frecuentes para el que ninguno de sus supersets (itemsets de tamaño \(\small{k}\) que contengan al de tamaño \(\small{k-1}\)) es frecuente.
Itemset cerrado: itemset para el que ninguno de sus supersets tiene el mismo soporte. Todos los itemsets maximales frecuentes son cerrados.
El algoritmo Apriori para generar reglas contiene los siguientes pasos:
Se comienza evaluando las reglas que tienen un item en el consecuente (parte derecha de la regla). Se mantienen las que tengan una confianza alta. A continuación se sigue el mismo proceso con las de tamaño 2 y así sucesivamente. Si el tamaño de los consecuentes es menor que el tamaño del itemset, es decir, si \(\small{k>m+1}\), se generan los consecuentes de tamaño siguiente. Se calcula la confianza dividiendo el soporte del consecuente y antecedente entre el soporte del antecedente. Si se supera la confianza mínima (\(\small{conf≥minconf}\)), se genera la regla. De lo contrario, se elimina el consecuente. Se podan aquellas reglas que no cumplen el soporte.
El algoritmo Frequent-Pattern Growth supone una mejora respecto al algoritmo Apriori en cuanto a que evita los inconvenientes de este último: generación de un gran número de itemsets candidatos y la necesidad de realizar varias pasadas a la base de datos para dicha generación en cada paso, lo que puede ralentizar el algoritmo si la base de datos es muy grande. FP-Growth supera estos inconvenientes compactando la base de datos utilizando un árbol FP o Frequent-Pattern tree (FP-tree). La base de datos compactada se divide en bases de datos condicionales y se obtienen de ellas los itemsets frecuentes, sin la generación de candidatos y con solo dos barridoss a la base de datos. El primer barrido determina el soporte de cada item para eliminar los no frecuentes. Los items frecuentes mantenidos se ordenan en orden descendiente de soporte en cada transacción. En un segundo barrido se analiza cada transacción para generar el árbol FP.
Un ejemplo de los pasos llevados a cabo para obtener un árbol FP para un conjunto de transacciones es el siguiente:
El árbol se genera leyendo los datos una transacción a la vez, asignándola a un recorrido en la estructura del árbol FP. La estructura comienza con un primer nodo nulo. Después cada transacción se itera una a una, añadiendo al árbol cada uno de los items como nodos enlazados en orden de ocurrencia. Cada nodo asociado a un item contiene a demás un conteo del número de veces ha aparecido en la trayectoria, lo que evita su almacenamiento múltiples veces ayudando a su vez a la compresión de los datos. Por ejemplo, la primera transacción {\(\small{a}\), \(\small{b}\)} dará lugar a la trayectoria \(\small{null \rightarrow a \rightarrow b}\), cada item con un contador de 1. La segunda transacción genera una nueva rama \(\small{null \rightarrow b \rightarrow c \rightarrow d}\), cuyos contadores también se inician en 1. Como diferentes transacciones pueden compartir mismos items, sus caminos pueden solaparse. En este caso, el item \(\small{b}\) de la primera transacción se enlaza con el de la segunda transacción. La tercera transacción comparte el prefijo \(\small{a}\) con la primera transacció, por lo que su camino empezará en este nodo, y su contador se incrementará en 1. Este proceso continúa hasta que se procesan todas las transacciones.
Como resultado obtenemos un árbol con un tamaño menor a la base de datos original.
Una vez obtenido el árbol, se generan los itemsets frecuentes recorriéndolo en sentido ascendente. En el ejemplo obtenido, se comenzaría buscando los itemsets frecuentes acabados en \(\small{e}\), después los acabados en \(\small{de}\), \(\small{ce}\), …, \(\small{d}\), \(\small{cd}\), etc. Por ejemplo, si queremos saber si el itemset \(\small{e}\) es frecuente, sumamos los contadores de los nodos donde aparece: 1 \(\small{1+1+1=3}\). Si el soporte mínimo establecido fuera de 4, los itemsets con \(\small{e}\) y sus combinaciones se descartarían porque no superan el soporte mínimo. Si el soporte mínimo fuera mayor, se mantendrían como itemsets frecuentes. Siguiente este proceso para los itemsets acabados en \(\small{d, c, b}\) y \(\small{a}\), obtendríamos los siguientes itemsets frecuentes:
Pese a las ventajas que presenta el algoritmo FP-Growth con respecto al algoritmo Apriori, también cuenta con algunas desventajas:
Puede que el árbol FP no quepa en memoria
La construcción del árbol FP es costosa, pero una vez obtenido, encontrar los itemsets frecuentes es fácil
Las reglas de asociación se generan a partir de los itemsets frecuentes obtenidos en el paso anterior. Cada itemset frecuente \(\small{Y}\) puede generar \(\small{2^k - 2}\) reglas de asociación. A partir de un itemset frecuente \(\small{Y}\) se crea una regla de asociación dividiendo \(\small{Y}\) en dos conjuntos disjuntos: \(\small{X}\) e \(\small{Y/X}\). Por ejemplo, el itemset frecuente \(\small{\{a, b, c\}}\) puede generar las siguientes reglas de asociación:
Si la regla \(\small{X \implies Y/X}\) supera la confianza mínima, se crea. Las reglas con confianza mínima, se podan:
Es importante contar con un criterio que evalúe las reglas obtenidas, que en aplicaciones reales pueden llegar a ser miles o millones. Pueden aplicarse criterios objetivos estadísticos, o subjetivos dependientes del dominio. Algunos de ellos son:
Por ejemplo, el uso del soporte podría presentar problemas en cuanto a la pérdida de reglas interesantes en casos con distribuciones asimétricas de itemsets, como la siguiente:
Por otro lado, reglas con una confianza alta podrían perderse ya que su cálculo no tiene en cuenta el soporte del consecuente (parte derecha de la regla).
El lift es una medida que cuantifica la relación entre \(\small{X}\) e \(\small{Y}\). Indica la proporción entre el soporte observado de un conjunto de items respecto de su soporte teórico bajo el supuesto de independencia. Dicho de otro modo, compara la frecuencia de un patrón observado con respecto a lo que se esperaría ver ese patrón solo por azar.
Dada la siguiente tabla de contingencia:
donde \(\small{f_{11}}\) indica el número de transacciones donde \(\small{p}\) y \(\small{q}\) están presentes, y \(\small{f_{00}}\) el número de transacciones donde \(\small{p}\) y \(\small{q}\) no están presentes, el lift calcula de la siguiente forma:
La interpretación del valor del lift es la siguiente:
\(\small{lift = 1}\) indica que \(\small{p}\) y \(\small{q}\) son independientes, o lo que es lo mismo, que la regla no representa un patrón real.
\(\small{lift < 1}\) indica que \(\small{p}\) y \(\small{q}\) están correlacionadas negativamente.
\(\small{lift > 1}\) indica que \(\small{p}\) y \(\small{q}\) están correlacionadas positivamente.
La correlación es una medida basada en medir la relación entre dos variables. Para variables binarias se utiliza el coeficiente:
Su valor varía en un rango [-1, 1], de una correlación negativa perfecta a una correlación positiva perfecta.
Su cálculo es útil con variables binarias simétricas. Una limitación es que se ve afectado por cambios proporcionales en el tamaño de las muestras.
Para el caso de variables binarias asimétricas se propone la medida IS:
Esta medida tenderá a ser baja cuando cualquiera de las reglas \(\small{p \rightarrow q}\) y \(\small{q \rightarrow p}\) tenga una confianza baja.
Tener en cuenta que sufre de los mismos problemas que la confianza: puede ser alta incluso para variables negativamente correlacionadas o no correlacionadas.
A continuación se muestra un ejemplo de obtención de reglas de asociación a partir de un conjunto de datos (orders.csv
) que contiene 12500 pedidos (transacciones) en un establecimiento de alimentación. El archivo puede descargarse desde Github.
library(readr)
pedidos <- read.csv(file = "./orders.csv", header = TRUE, sep = ";")
head(pedidos)
## order_id product_name
## 1 2 Organic Egg Whites
## 2 2 Michigan Organic Kale
## 3 2 Garlic Powder
## 4 2 Coconut Butter
## 5 2 Natural Sweetener
## 6 2 Carrots
Los datos se encuentran almacenados en formato single o tabla larga, donde cada transacción está formada por un conjunto de items que se compran juntos. Sin embargo, cada línea contiene un solo item, por ello hay incluida una columna con el ID de la transacción o pedido (order_id
) al que corresponde cada item (product_name
). Si los datos estuvieran almacenados en formato basket, no sería imprescindible esta columna.
Para el análisis utilizaremos el paquete de arules
, que trabaja con datos en formato de tipo transactions
. La función read.transactions()
del paquete arules
nos permite leer los datos en formato basket o single a objetos de tipo transactions
. Los argumentos de esta función son:
file
: nombre del archivo con los datos
format
: formato de los datos a importar (single
o basket
)
header
: variable lógica para indicar la presencia de los nombres de las variables en la primera fila de los datos
sep
: caracter de separación de los datos en el archivo original
cols
: Para el formato single, vector numérico o character de longitud dos para indicar el número o nombre de las columnas.
rm.duplicates
: valor lógico para indicar si queremos eliminar items duplicados
skip
: nombre de filas a omitir
Importante tener en cuenta que los objetos de tipo transactions
reformatean los datos a una matriz booleada (presencia (1) o no (0) de cada item en cada transacción) con transacciones en filas e items en columnas. Por tanto, si contamos con datos numéricos, hay que discretizarlos.
library(arules)
# Cargamos los datos a un objeto de tipo transaccion
transacciones <- read.transactions(file = "./orders.csv",
header = TRUE,
format = "single",
sep = ";",
cols = c("order_id", "product_name"),
rm.duplicates = TRUE)
# El objeto contiene transacciones en filas e items en columnas
rownames(transacciones)[1:3]
## [1] "100" "1000" "1002"
colnames(transacciones)[1:3]
## [1] "#2 Coffee Filters"
## [2] "#4 Natural Brown Coffee Filters"
## [3] "& Go! Hazelnut Spread + Pretzel Sticks"
# Dimensiones
transacciones
## transactions in sparse format with
## 12500 transactions (rows) and
## 17917 items (columns)
Como podemos ver, hay involucrados un total de 17917 items.
Podemos hacer también una inspección rápida de qué items hay en las transacciones:
# Inspeccion de los items en cada transaccion
inspect(transacciones[1:2])
## items transactionID
## [1] {Soda,
## Spring Water} 100
## [2] {Cacao Sweet Raw Chocolate Nibs,
## Jazz Apple,
## No. 01 Organic Vegan Cold Pressed Juice Kale Spinach Romaine Celery Cucumber Apple Lemon,
## Organic Baby Kale Mix,
## Organic Unsweetened Almond Milk,
## Pitted Dates,
## Whole Chia Seeds} 1000
También podemos obtener el tamaño de todas las transacciones:
library(ggplot2)
# Tamanhos de todas las transacciones
tamanhos_trans <- data.frame(tamanho = size(transacciones))
head(tamanhos_trans)
## tamanho
## 1 2
## 2 7
## 3 33
## 4 11
## 5 1
## 6 3
# Distribucion del tamanho de todas las transacciones
ggplot(tamanhos_trans, aes(x = tamanho)) +
geom_density(fill = "orangered3") +
labs(x = "Tamaño de las transacciones") +
theme_bw()
# Distribucion del tamahno de las transacciones por cuantiles
summary(tamanhos_trans)
## tamanho
## Min. : 1.000
## 1st Qu.: 4.000
## Median : 8.000
## Mean : 9.354
## 3rd Qu.:13.000
## Max. :68.000
El número máximo de items en un pedido es de 68, y el mínimo es de 1. La mitad de clientes compran un máximo de 8 items.
También podemos obtener el soporte de cada uno de los items en el conjunto de transacciones con la función itemFrequency()
:
# Frecuencia de cada item
head(itemFrequency(transacciones))
## #2 Coffee Filters
## 0.00024
## #4 Natural Brown Coffee Filters
## 0.00008
## & Go! Hazelnut Spread + Pretzel Sticks
## 0.00016
## \\"Darn Good\\" Chili Mix
## 0.00008
## \\"Mokaccino\\" Milk + Blue Bottle Coffee Chocolate
## 0.00016
## 0 Calorie Acai Raspberry Water Beverage
## 0.00008
Como nos interesa conocer qué productos aparecen juntos en los pedidos, restringiremos las transacciones a aquellas que contengan al menos dos items:
# Mantenemos las transacciones con al menos dos items
transacciones <- transacciones[tamanhos_trans > 1]
dim(transacciones)
## [1] 11733 17917
Este filtrado ha supuesto una reducción de 767 transacciones.
El soporte hace referencia al número de transacciones que contienen un itemset dividido entre el total de transacciones. En este ejemplo debemos considerar que contamos con datos de alta dimensionalidad (11733 x 17917), por lo que el soporte tendrá que ser bastante pequeño al esperar que cada evento sea “poco común”. Consideremos que un itemset es frecuente cuando aparece en al menos 25 transacciones (se ha comprado al menos 25 veces). Como confianza estableceremos un 65%.
# Umbral de soporte
soporte <- 15/dim(transacciones)[1]
soporte
## [1] 0.001278445
# Umbral de confianza
confianza <- 0.7
El soporte obtenido corresponde al 0,12%.
Para saber el número de itemsets frecuentes con el soporte establecido, aplicaremos el algoritmo Apriori con la función apriori()
. Cuenta con los siguientes argumentos principales:
data
: objeto de tipo transactions
.
parameter
: lista que incluye el valor mínimo de soporte (support
), confianza (confidence
), máximo/mínimo de items en cada itemset (maxlen
, minlen
), etc. Para obtener itemsets frecuentes indicar target = "frequent itemsets"
, y para obtener las reglas indicar target = "rules"
.
appearance
: patrones para restringir la aparición de items.
control
: lista para especificar parámetros que controlen el algoritmo.
# Busqueda de itemsets frecuentes
itemsets_frecuentes <- apriori(data = transacciones,
parameter = list(support = soporte,
target = "frequent itemsets"),
control = list(verbose = FALSE))
summary(itemsets_frecuentes)
## set of 2590 itemsets
##
## most frequent items:
## Banana Bag of Organic Bananas Organic Strawberries
## 218 174 148
## Organic Baby Spinach Organic Hass Avocado (Other)
## 138 126 3170
##
## element (itemset/transaction) length distribution:sizes
## 1 2 3
## 1314 1168 108
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.000 1.000 1.000 1.534 2.000 3.000
##
## summary of quality measures:
## support transIdenticalToItemsets count
## Min. :0.001364 Min. :0.000e+00 Min. : 16.00
## 1st Qu.:0.001619 1st Qu.:0.000e+00 1st Qu.: 19.00
## Median :0.002131 Median :0.000e+00 Median : 25.00
## Mean :0.003504 Mean :4.472e-05 Mean : 41.11
## 3rd Qu.:0.003324 3rd Qu.:8.523e-05 3rd Qu.: 39.00
## Max. :0.145743 Max. :2.557e-03 Max. :1710.00
##
## includes transaction ID lists: FALSE
##
## mining info:
## data ntransactions support confidence
## transacciones 11733 0.001278445 1
Según el output obtenido, podemos ver que hay un total de 2590 itemsets frecuentes, que son los que superan el soporte mínimo establecido. La mayoría de ellos (1314) están formados por 1 item. De todos ellos, los seis que presentan el soporte más alto son:
# Top itemsets mas frecuentes
top6_itemsets <- sort(itemsets_frecuentes, by = "support", decreasing = TRUE)[1:6]
inspect(top6_itemsets)
## items support transIdenticalToItemsets count
## [1] {Banana} 0.14574278 0.0025568908 1710
## [2] {Bag of Organic Bananas} 0.11957726 0.0019602830 1403
## [3] {Organic Strawberries} 0.08003068 0.0007670672 939
## [4] {Organic Baby Spinach} 0.07628058 0.0006818376 895
## [5] {Organic Hass Avocado} 0.06878036 0.0004261485 807
## [6] {Organic Avocado} 0.05284241 0.0005966079 620
library(dplyr)
as(top6_itemsets, Class = "data.frame") %>%
ggplot(aes(x = reorder(items, support), y = support)) +
geom_col(fill = "skyblue3", width = 0.5) +
coord_flip() +
labs(y = "soporte", x = "itemsets") +
theme_bw()
Podemos también obtener la cantidad de itemsets frecuentes que contienen un determinado item o items con la función subset()
, y alguno de los siguientes operadores:
Operador | Función |
---|---|
& |
AND |
|| |
OR |
%in% |
contiene cualquiera de los items |
%ain% |
contiene todos los items |
%pin% |
contiene parcialmente los items |
Por ejemplo, para filtrar los itemsets frecuentes que contienen Banana:
# Itemsets frecuentes que contienen "Banana"
itemsets_bananas <- arules::subset(itemsets_frecuentes,
subset = items %ain% "Banana")
inspect(itemsets_bananas[1:5])
## items support
## [1] {Banana} 0.145742777
## [2] {1% Low Fat Milk,Banana} 0.001363675
## [3] {Banana,Cheddar Bunnies Snack Crackers} 0.001448905
## [4] {Banana,Mandarin Oranges} 0.001363675
## [5] {Banana,Frozen Broccoli Florets} 0.001448905
## transIdenticalToItemsets count
## [1] 2.556891e-03 1710
## [2] 8.522969e-05 16
## [3] 0.000000e+00 17
## [4] 0.000000e+00 16
## [5] 0.000000e+00 17
# Obtencion de reglas de asociacion
reglas <- apriori(data = transacciones,
parameter = list(support = soporte,
confidence = confianza,
target = "rules"),
control = list(verbose = FALSE))
print(paste("Reglas generadas:", length(reglas)))
## [1] "Reglas generadas: 7"
summary(reglas)
## set of 7 rules
##
## rule length distribution (lhs + rhs):sizes
## 2 3
## 2 5
##
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.000 2.500 3.000 2.714 3.000 3.000
##
## summary of quality measures:
## support confidence coverage lift
## Min. :0.001364 Min. :0.7143 Min. :0.001449 Min. : 34.41
## 1st Qu.:0.001364 1st Qu.:0.7560 1st Qu.:0.001747 1st Qu.:161.45
## Median :0.001364 Median :0.7619 Median :0.001790 Median :258.82
## Mean :0.001485 Mean :0.7913 Mean :0.001899 Mean :227.92
## 3rd Qu.:0.001577 3rd Qu.:0.8048 3rd Qu.:0.002088 3rd Qu.:322.03
## Max. :0.001790 Max. :0.9412 Max. :0.002386 Max. :335.23
## count
## Min. :16.00
## 1st Qu.:16.00
## Median :16.00
## Mean :17.43
## 3rd Qu.:18.50
## Max. :21.00
##
## mining info:
## data ntransactions support confidence
## transacciones 11733 0.001278445 0.7
Como vemos, con los parámetros establecidos se han encontrado un total de 7 reglas, con un lift mínimo de 34’41 (>>1), lo que indica patrones potencialmente reales en las compras. Cinco de las reglas contienen 3 items en el antecedente (lhs), y las otras dos contienen 2 items:
# Reglas obtenidas ordenadas por orden descendente de confianza
inspect(sort(reglas, decreasing = TRUE, by = "confidence"))
## lhs rhs support confidence coverage lift count
## [1] {Blueberry Whole Milk Yogurt Pouch,
## Yotoddler Organic Pear Spinach Mango Yogurt} => {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} 0.001363675 0.9411765 0.001448905 324.78893 16
## [2] {Lime Sparkling Water,
## Pure Sparkling Water} => {Sparkling Water Grapefruit} 0.001448905 0.8095238 0.001789824 34.41356 17
## [3] {Blueberry Whole Milk Yogurt Pouch,
## Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} => {Yotoddler Organic Pear Spinach Mango Yogurt} 0.001363675 0.8000000 0.001704594 335.22857 16
## [4] {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch,
## Yotoddler Organic Pear Spinach Mango Yogurt} => {Blueberry Whole Milk Yogurt Pouch} 0.001363675 0.7619048 0.001789824 319.26531 16
## [5] {Total 2% Lowfat Greek Strained Yogurt With Blueberry,
## Total 2% Lowfat Greek Strained Yogurt with Peach} => {Total 2% with Strawberry Lowfat Greek Strained Yogurt} 0.001363675 0.7619048 0.001789824 76.40537 16
## [6] {Yotoddler Organic Pear Spinach Mango Yogurt} => {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} 0.001789824 0.7500000 0.002386431 258.81618 21
## [7] {Blueberry Whole Milk Yogurt Pouch} => {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} 0.001704594 0.7142857 0.002386431 246.49160 20
Una vez obtenidas las reglas, tenemos la posibilidad de establecer restricciones o filtros. Por ejemplo, para manterner solo las que contengan “Blueberry Whole Milk Yogurt Pouch” en el antecedente, con una confianza superior al 90%:
reglas_filtradas <- subset(reglas,
subset = lhs %ain% "Blueberry Whole Milk Yogurt Pouch" &
confidence > 0.9)
inspect(reglas_filtradas)
## lhs rhs support confidence coverage lift count
## [1] {Blueberry Whole Milk Yogurt Pouch,
## Yotoddler Organic Pear Spinach Mango Yogurt} => {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} 0.001363675 0.9411765 0.001448905 324.7889 16
Podemos obtener también las reglas maximales, que son aquellas que están generadas por itemsets maximales, con la función is.maximal()
:
reglas_maximales <- reglas[is.maximal(reglas)]
reglas_maximales
## set of 5 rules
inspect(reglas_maximales)
## lhs rhs support confidence coverage lift count
## [1] {Blueberry Whole Milk Yogurt Pouch,
## Yotoddler Organic Pear Spinach Mango Yogurt} => {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} 0.001363675 0.9411765 0.001448905 324.78893 16
## [2] {Blueberry Whole Milk Yogurt Pouch,
## Organic Whole Milk Strawberry Beet Berry Yogurt Pouch} => {Yotoddler Organic Pear Spinach Mango Yogurt} 0.001363675 0.8000000 0.001704594 335.22857 16
## [3] {Organic Whole Milk Strawberry Beet Berry Yogurt Pouch,
## Yotoddler Organic Pear Spinach Mango Yogurt} => {Blueberry Whole Milk Yogurt Pouch} 0.001363675 0.7619048 0.001789824 319.26531 16
## [4] {Total 2% Lowfat Greek Strained Yogurt With Blueberry,
## Total 2% Lowfat Greek Strained Yogurt with Peach} => {Total 2% with Strawberry Lowfat Greek Strained Yogurt} 0.001363675 0.7619048 0.001789824 76.40537 16
## [5] {Lime Sparkling Water,
## Pure Sparkling Water} => {Sparkling Water Grapefruit} 0.001448905 0.8095238 0.001789824 34.41356 17
Cinco de las siete reglas son maximales.
Podríamos también buscar reglas para determinar qué item/s están relacionados con alguno en específico:
# Reglas con items relacionados con Sparkling Water Grapefruit
reglas_waterGrape <- apriori(transacciones,
parameter = list(support = soporte,
confidence = confianza,
target = "rules"),
appearance = list(rhs = "Sparkling Water Grapefruit",
default = "lhs"),
control = list(verbose = FALSE))
inspect(reglas_waterGrape)
## lhs rhs support confidence coverage lift count
## [1] {Lime Sparkling Water,
## Pure Sparkling Water} => {Sparkling Water Grapefruit} 0.001448905 0.8095238 0.001789824 34.41356 17
Existen un amplio conjunto de métricas que podemos calcular con la función interestMeasure()
para las reglas generadas. Por ejemplo, podemos calcular el test exacto de Fisher (test de significancia para obtener si las reglas representan patrones reales) y añadirlo al conjunto de reglas.
testFisher <- interestMeasure(reglas,
measure = "fishersExactTest",
transactions = transacciones)
summary(testFisher)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000e+00 0.000e+00 0.000e+00 9.942e-26 3.220e-29 6.959e-25
Todos los p-valores del test son pequeños (menores a 0), lo que refleja que es muy probable que las reglas reflejen patrones de comportamiento en los pedidos.
# Añadimos los indices al conjunto de reglas
quality(reglas) <- cbind(quality(reglas), testFisher)
El paquete aruleViz
nos ofrece distintas posibilidades para visualizar reglas de asociación, aquí se muestran solo algunas:
library(arulesViz)
# Grafico de dispersion coloreado en funcion del lift
plot(reglas, measure = c("support", "confidence"), shading = "lift")
# Grafico de dispersion coloreado en funcion del numero de items
plot(reglas, measure = c("support", "confidence"), shading = "order")
# Grafico de coordenadas paralelas. Cada regla queda representada por una recta
# que va de izquierda a derecha. El eje Y representa cada uno de los items, y el
# eje X su posicion dentro de la regla
plot(reglas, method = "paracoord")
Pang-Ning Tan, Michael Steinbach, Vipin Kumar, et al. Introduction to data mining, volume 1. Pearson Addison Wesley Boston, 2006.
R. Agrawal and R. Srikant. Fast algorithms for mining association rules. In Proc 20th Int Conf Very Large Data Bases VLDB, volume 1215, pages 487-499. Citeseer, 1994.
Nina Zumel and John Mount. Practical Data Science with R, Second Edition (2019).
This work by Cristina Gil Martínez is licensed under a Creative Commons Attribution 4.0 International License.