23  FP-Growth y minería de patrones frecuentes

Autor/a

Diego Villalba

Fecha de publicación

19 de mayo de 2026

24 FP-Growth y minería de patrones frecuentes

24.1 Introducción

La minería de reglas de asociación busca descubrir regularidades en bases de datos transaccionales: productos que suelen comprarse juntos, páginas que suelen visitarse en una misma sesión, palabras que coaparecen en documentos o eventos que tienden a registrarse en conjunto. En este contexto, una transacción representa una observación compuesta por varios ítems; por ejemplo, una compra de supermercado puede contener {Pan, Leche, Pañales}. El objetivo no es predecir una etiqueta, sino identificar estructuras de coocurrencia que permitan extraer conocimiento interpretable a partir de datos discretos (Agrawal y Srikant 1994; Han, Kamber, y Pei 2012).

El algoritmo FP-Growth (Frequent Pattern Growth) fue propuesto como una alternativa eficiente a Apriori para encontrar conjuntos frecuentes de ítems. Su idea central es evitar la generación explícita de candidatos y comprimir la base de transacciones en una estructura llamada FP-tree (Frequent Pattern Tree). A partir de ese árbol, el algoritmo explora patrones frecuentes mediante bases condicionales y árboles condicionales (Han, Pei, y Yin 2000; Borgelt 2005).

Este capítulo desarrolla FP-Growth de manera progresiva. Primero se revisan las nociones de transacción, itemset, soporte y frecuencia. Después se muestra cómo construir un FP-tree usando un ejemplo pequeño de cesta de compra. Finalmente, se explica cómo extraer patrones frecuentes mediante caminos prefijo condicionales, se compara FP-Growth con Apriori y se implementa un flujo práctico en Python.

24.2 Conceptos básicos

En minería de asociaciones, trabajamos con una colección de transacciones. Cada transacción contiene un subconjunto de ítems tomado de un universo finito de productos, términos o eventos posibles. Esta representación es natural en problemas donde los datos son conjuntos: una compra contiene productos, un documento contiene palabras, una sesión web contiene páginas visitadas.

Definición. Sea \(I = \{i_1, i_2, \ldots, i_m\}\) un conjunto finito de ítems. Una transacción \(T\) es un subconjunto de \(I\), es decir: \[ T \subseteq I. \] Una base transaccional es una colección \(\mathcal{D} = \{T_1,T_2,\ldots,T_n\}\) de transacciones.

Definición. Un itemset es cualquier subconjunto \(X \subseteq I\). Decimos que una transacción \(T_i\) contiene a \(X\) si todos los ítems de \(X\) aparecen en \(T_i\): \[ X \subseteq T_i. \]

El concepto clave para decidir si un patrón es relevante es el soporte. Existen dos formas comunes de reportarlo: como conteo absoluto o como proporción. El conteo absoluto indica cuántas transacciones contienen el patrón; el soporte relativo divide ese conteo entre el número total de transacciones.

Definición. El soporte absoluto de un itemset \(X\) en una base transaccional \(\mathcal{D}\) es el número de transacciones que contienen a \(X\): \[ \operatorname{supp}_{\#}(X)=\left|\{T_i \in \mathcal{D}: X \subseteq T_i\}\right|. \] El soporte relativo se define como: \[ \operatorname{supp}(X)=\frac{\operatorname{supp}_{\#}(X)}{|\mathcal{D}|}. \tag{1}\]

Definición. Dado un umbral mínimo de soporte \(\text{min\_sup}\), un itemset \(X\) es frecuente si su soporte absoluto cumple: \[ \operatorname{supp}_{\#}(X) \geq \text{min\_sup}. \tag{2}\]

El umbral \(\text{min\_sup}\) controla la granularidad del análisis. Un valor demasiado bajo puede producir demasiados patrones, muchos de ellos triviales o difíciles de interpretar. Un valor demasiado alto puede eliminar patrones interesantes pero menos comunes. Por ello, en aplicaciones reales suele elegirse mediante exploración, conocimiento del dominio y restricciones computacionales.

24.3 De Apriori a FP-Growth

El algoritmo Apriori explota una propiedad fundamental: si un conjunto de ítems es frecuente, entonces todos sus subconjuntos también son frecuentes. De manera equivalente, si un itemset no es frecuente, ningún superconjunto suyo puede ser frecuente (Agrawal y Srikant 1994). Esta propiedad permite podar el espacio de búsqueda, pero Apriori todavía necesita generar muchos candidatos y escanear la base varias veces.

FP-Growth sigue otra estrategia. En lugar de construir y evaluar candidatos explícitamente, realiza dos recorridos principales sobre la base de datos: uno para calcular los soportes de los ítems individuales y otro para construir un árbol compacto. Después extrae patrones frecuentes desde la estructura comprimida (Han, Pei, y Yin 2000).

La ventaja aparece especialmente cuando muchas transacciones comparten prefijos. Si los ítems se ordenan globalmente por frecuencia decreciente, transacciones parecidas tienden a compartir las primeras ramas del árbol. Así, el FP-tree almacena información agregada en lugar de repetir cada transacción completa.

24.4 Ejemplo base: transacciones de cesta de compra

Considérese la siguiente base de transacciones y un soporte mínimo absoluto \(\text{min\_sup}=3\):

Transacción Ítems
\(T_1\) {Pan, Leche}
\(T_2\) {Pan, Leche, Pañales, Cerveza}
\(T_3\) {Leche, Pañales, Cerveza}
\(T_4\) {Pan, Leche, Pañales, Cerveza}
\(T_5\) {Pan, Leche, Pañales}

Los soportes absolutos de los ítems individuales son:

Ítem Transacciones donde aparece Soporte absoluto
Pan \(T_1,T_2,T_4,T_5\) 4
Leche \(T_1,T_2,T_3,T_4,T_5\) 5
Pañales \(T_2,T_3,T_4,T_5\) 4
Cerveza \(T_2,T_3,T_4\) 3

Como todos los ítems tienen soporte absoluto mayor o igual que \(3\), ninguno se elimina en esta etapa. Si hubiera ítems con soporte menor que \(\text{min\_sup}\), se descartarían antes de construir el árbol.

Mostrar código
# Ejemplo base de transacciones
transactions = [
    {"Pan", "Leche"},
    {"Pan", "Leche", "Pañales", "Cerveza"},
    {"Leche", "Pañales", "Cerveza"},
    {"Pan", "Leche", "Pañales", "Cerveza"},
    {"Pan", "Leche", "Pañales"},
]

min_sup = 3

from collections import Counter

item_counts = Counter()
for transaction in transactions:
    item_counts.update(transaction)

item_counts
Counter({'Leche': 5, 'Pan': 4, 'Pañales': 4, 'Cerveza': 3})

24.5 Ordenamiento por frecuencia

El FP-tree depende de un orden global de ítems. La regla usual consiste en ordenar los ítems de mayor a menor frecuencia. En caso de empates, conviene fijar un criterio determinista, por ejemplo orden alfabético. Este ordenamiento hace que transacciones con ítems frecuentes compartan prefijos y que el árbol sea más compacto.

En el ejemplo, el orden global puede tomarse como:

\[ \text{Leche} \succ \text{Pan} \succ \text{Pañales} \succ \text{Cerveza}. \]

Con ese orden, las transacciones se transforman en:

Transacción original Transacción ordenada
{Pan, Leche} [Leche, Pan]
{Pan, Leche, Pañales, Cerveza} [Leche, Pan, Pañales, Cerveza]
{Leche, Pañales, Cerveza} [Leche, Pañales, Cerveza]
{Pan, Leche, Pañales, Cerveza} [Leche, Pan, Pañales, Cerveza]
{Pan, Leche, Pañales} [Leche, Pan, Pañales]
Mostrar código
# Orden global por frecuencia descendente y desempate alfabético
frequent_items = {item for item, count in item_counts.items() if count >= min_sup}
order = sorted(frequent_items, key=lambda item: (-item_counts[item], item))
rank = {item: position for position, item in enumerate(order)}

ordered_transactions = []
for transaction in transactions:
    filtered = [item for item in transaction if item in frequent_items]
    ordered = sorted(filtered, key=lambda item: rank[item])
    ordered_transactions.append(ordered)

order, ordered_transactions
(['Leche', 'Pan', 'Pañales', 'Cerveza'],
 [['Leche', 'Pan'],
  ['Leche', 'Pan', 'Pañales', 'Cerveza'],
  ['Leche', 'Pañales', 'Cerveza'],
  ['Leche', 'Pan', 'Pañales', 'Cerveza'],
  ['Leche', 'Pan', 'Pañales']])

24.6 Construcción del FP-tree

Un FP-tree es un árbol con raíz nula. Cada nodo almacena un ítem, un contador y enlaces hacia sus hijos. Para insertar una transacción ordenada, se recorre la transacción de izquierda a derecha. Si el siguiente ítem ya existe como hijo del nodo actual, se incrementa su contador. Si no existe, se crea un nuevo nodo con contador inicial igual a uno.

Definición. Un FP-tree es una estructura arbórea \(\mathcal{T}\) donde cada nodo no raíz representa un ítem y almacena un contador. El contador de un nodo indica cuántas transacciones comparten el prefijo correspondiente al camino desde la raíz hasta ese nodo: \[ \operatorname{count}(v)=\left|\{T_i \in \mathcal{D}: \operatorname{path}(v) \subseteq T_i\}\right|. \]

El procedimiento de construcción puede resumirse así:

  1. Crear una raíz null.
  2. Ordenar cada transacción de acuerdo con la frecuencia global.
  3. Insertar cada transacción en el árbol.
  4. Incrementar contadores cuando una rama ya existe.
  5. Crear nodos nuevos cuando el prefijo todavía no aparece.
Mostrar código
class FPNode:
    def __init__(self, item=None, count=0, parent=None):
        self.item = item
        self.count = count
        self.parent = parent
        self.children = {}

    def add_child(self, item):
        child = FPNode(item=item, count=0, parent=self)
        self.children[item] = child
        return child


def insert_transaction(root, transaction):
    current = root
    for item in transaction:
        if item not in current.children:
            current.add_child(item)
        current = current.children[item]
        current.count += 1


def build_fp_tree(ordered_transactions):
    root = FPNode(item="null", count=0)
    for transaction in ordered_transactions:
        insert_transaction(root, transaction)
    return root


def print_tree(node, indent=0):
    label = f"{node.item}: {node.count}" if node.item != "null" else "null"
    print("  " * indent + label)
    for child in node.children.values():
        print_tree(child, indent + 1)

root = build_fp_tree(ordered_transactions)
print_tree(root)
null
  Leche: 5
    Pan: 4
      Pañales: 3
        Cerveza: 2
    Pañales: 1
      Cerveza: 1

En este ejemplo, la rama más importante inicia con Leche, porque aparece en todas las transacciones. Desde Leche, varias transacciones continúan con Pan; otras continúan directamente con Pañales. La compresión proviene de sumar contadores en prefijos compartidos en lugar de almacenar cada transacción de forma independiente.

24.7 Caminos prefijo y base condicional

Una vez construido el FP-tree, FP-Growth extrae patrones frecuentes considerando los ítems desde los menos frecuentes hacia los más frecuentes. Para cada ítem objetivo, se buscan todos los caminos que terminan en ese ítem. Al quitar el ítem objetivo de esos caminos se obtiene su base de patrones condicional.

Definición. Dado un ítem \(a\), la base de patrones condicional de \(a\), denotada \(\mathcal{B}_a\), es el multiconjunto de caminos prefijo que aparecen antes de \(a\) en el FP-tree, ponderados por el contador del nodo asociado a \(a\): \[ \mathcal{B}_a = \{(P_j,c_j): P_j \text{ es un camino prefijo de } a \text{ y } c_j \text{ es su conteo}\}. \]

Para el ítem Cerveza, los caminos relevantes son:

Camino en el árbol Conteo
[Leche, Pan, Pañales, Cerveza] 2
[Leche, Pañales, Cerveza] 1

Al eliminar Cerveza, se obtiene:

Camino prefijo Conteo
[Leche, Pan, Pañales] 2
[Leche, Pañales] 1

En esta base condicional, los conteos acumulados son:

Ítem Conteo condicional
Leche 3
Pan 2
Pañales 3

Con \(\text{min\_sup}=3\), Pan se elimina de la base condicional de Cerveza, mientras que Leche y Pañales permanecen. Por tanto, los patrones frecuentes que incluyen Cerveza son:

\[ \{\text{Cerveza}\}, \quad \{\text{Leche},\text{Cerveza}\}, \quad \{\text{Pañales},\text{Cerveza}\}, \quad \{\text{Leche},\text{Pañales},\text{Cerveza}\}. \]

Mostrar código
def collect_prefix_paths(node, target_item):
    """Devuelve caminos prefijo hacia target_item dentro de un FP-tree simple."""
    paths = []

    def traverse(current):
        for child in current.children.values():
            if child.item == target_item:
                path = []
                parent = child.parent
                while parent is not None and parent.item != "null":
                    path.append(parent.item)
                    parent = parent.parent
                path.reverse()
                if path:
                    paths.append((path, child.count))
            traverse(child)

    traverse(node)
    return paths

prefix_paths_cerveza = collect_prefix_paths(root, "Cerveza")
prefix_paths_cerveza
[(['Leche', 'Pan', 'Pañales'], 2), (['Leche', 'Pañales'], 1)]
Mostrar código
def conditional_counts(prefix_paths):
    counts = Counter()
    for path, weight in prefix_paths:
        for item in path:
            counts[item] += weight
    return counts

conditional_counts(prefix_paths_cerveza)
Counter({'Leche': 3, 'Pañales': 3, 'Pan': 2})

24.8 Árbol condicional

Después de obtener la base condicional de un ítem, se eliminan los ítems que no alcanzan el soporte mínimo y se construye un nuevo FP-tree restringido a esa base. Ese árbol se llama árbol condicional. En el caso de Cerveza, el árbol condicional conserva la estructura:

\[ \text{Leche}:3 \rightarrow \text{Pañales}:3. \]

Esto significa que, entre las transacciones que contienen Cerveza, existen tres ocurrencias donde Leche aparece junto con Cerveza y tres ocurrencias donde Pañales aparece junto con Cerveza. Además, el camino conjunto indica que {Leche, Pañales, Cerveza} también es frecuente.

Definición. El árbol condicional de un ítem \(a\) es el FP-tree construido a partir de la base condicional \(\mathcal{B}_a\) después de eliminar los ítems cuyo conteo condicional es menor que \(\text{min\_sup}\): \[ \mathcal{T}_a = \operatorname{FPtree}\left(\{P_j \in \mathcal{B}_a: \operatorname{count}_{\mathcal{B}_a}(i) \geq \text{min\_sup}\}\right). \]

Mostrar código
def expand_weighted_paths(prefix_paths):
    expanded = []
    for path, weight in prefix_paths:
        expanded.extend([path] * weight)
    return expanded

conditional_item_counts = conditional_counts(prefix_paths_cerveza)
conditional_frequent = {
    item for item, count in conditional_item_counts.items()
    if count >= min_sup
}

conditional_order = sorted(
    conditional_frequent,
    key=lambda item: (-conditional_item_counts[item], item)
)
conditional_rank = {item: pos for pos, item in enumerate(conditional_order)}

conditional_transactions = []
for path in expand_weighted_paths(prefix_paths_cerveza):
    filtered_path = [item for item in path if item in conditional_frequent]
    ordered_path = sorted(filtered_path, key=lambda item: conditional_rank[item])
    if ordered_path:
        conditional_transactions.append(ordered_path)

conditional_root = build_fp_tree(conditional_transactions)
print_tree(conditional_root)
null
  Leche: 3
    Pañales: 3

24.9 Patrones frecuentes del ejemplo

Repitiendo el procedimiento para los ítems restantes en orden ascendente de frecuencia, se obtienen los conjuntos frecuentes:

Ítem base Patrones frecuentes asociados
Cerveza {Cerveza}, {Leche, Cerveza}, {Pañales, Cerveza}, {Leche, Pañales, Cerveza}
Pañales {Pañales}, {Leche, Pañales}, {Pan, Pañales}, {Leche, Pan, Pañales}
Pan {Pan}, {Leche, Pan}
Leche {Leche}

Agrupando y eliminando duplicados, los itemsets frecuentes con \(\text{min\_sup}=3\) son:

\[ \begin{aligned} &\{\text{Leche}\},\{\text{Pan}\},\{\text{Pañales}\},\{\text{Cerveza}\},\\ &\{\text{Leche},\text{Pan}\},\{\text{Leche},\text{Pañales}\},\{\text{Leche},\text{Cerveza}\},\\ &\{\text{Pan},\text{Pañales}\},\{\text{Pañales},\text{Cerveza}\},\\ &\{\text{Leche},\text{Pan},\text{Pañales}\},\{\text{Leche},\text{Pañales},\text{Cerveza}\}. \end{aligned} \]

Es importante notar que FP-Growth no produce directamente reglas de asociación; primero produce itemsets frecuentes. Las reglas se construyen después a partir de esos itemsets, evaluando métricas como confianza, lift o convicción (Tan et al. 2019; Han, Kamber, y Pei 2012).

24.10 Implementación práctica con mlxtend

En Python, una forma sencilla de aplicar FP-Growth es utilizar mlxtend, que implementa tanto Apriori como FP-Growth para matrices transaccionales codificadas en formato one-hot (Raschka 2018).

Mostrar código
# Si es necesario, instalar previamente:
# pip install mlxtend pandas

import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import fpgrowth, association_rules

transactions_list = [list(t) for t in transactions]

encoder = TransactionEncoder()
one_hot = encoder.fit(transactions_list).transform(transactions_list)
df = pd.DataFrame(one_hot, columns=encoder.columns_)

df
Cerveza Leche Pan Pañales
0 False True True False
1 True True True True
2 True True False True
3 True True True True
4 False True True True

Como mlxtend usa soporte relativo, el umbral absoluto \(\text{min\_sup}=3\) debe transformarse dividiendo entre el número de transacciones:

\[ \text{min\_sup}_{rel}=\frac{3}{5}=0.6. \]

Mostrar código
min_support_relative = min_sup / len(transactions)

frequent_itemsets = fpgrowth(
    df,
    min_support=min_support_relative,
    use_colnames=True
)

frequent_itemsets.sort_values(
    by=["support", "itemsets"],
    ascending=[False, True]
)
support itemsets
0 1.0 (Leche)
1 0.8 (Pan)
2 0.8 (Pañales)
4 0.8 (Pan, Leche)
7 0.8 (Pañales, Leche)
3 0.6 (Cerveza)
5 0.6 (Pan, Pañales)
6 0.6 (Pan, Pañales, Leche)
8 0.6 (Pañales, Cerveza)
9 0.6 (Leche, Cerveza)
10 0.6 (Pañales, Leche, Cerveza)

A partir de los itemsets frecuentes se pueden generar reglas. Por ejemplo, una regla \(X \Rightarrow Y\) se interpreta como: “cuando aparece \(X\), también tiende a aparecer \(Y\)”.

Definición. La confianza de una regla de asociación \(X \Rightarrow Y\), con \(X \cap Y = \varnothing\), mide la proporción de transacciones que contienen \(X\) y también contienen \(Y\): \[ \operatorname{conf}(X \Rightarrow Y)=\frac{\operatorname{supp}(X \cup Y)}{\operatorname{supp}(X)}. \tag{3}\]

Definición. El lift de una regla \(X \Rightarrow Y\) compara la coocurrencia observada de \(X\) y \(Y\) con la coocurrencia esperada bajo independencia estadística: \[ \operatorname{lift}(X \Rightarrow Y)=\frac{\operatorname{supp}(X \cup Y)}{\operatorname{supp}(X)\operatorname{supp}(Y)}. \tag{4}\]

Mostrar código
rules = association_rules(
    frequent_itemsets,
    metric="confidence",
    min_threshold=0.7
)

selected_columns = [
    "antecedents", "consequents", "support", "confidence", "lift"
]

rules[selected_columns].sort_values(
    by=["lift", "confidence"],
    ascending=False
)
antecedents consequents support confidence lift
12 (Cerveza) (Pañales) 0.6 1.00 1.2500
16 (Leche, Cerveza) (Pañales) 0.6 1.00 1.2500
18 (Cerveza) (Pañales, Leche) 0.6 1.00 1.2500
11 (Pañales) (Cerveza) 0.6 0.75 1.2500
14 (Pañales, Leche) (Cerveza) 0.6 0.75 1.2500
17 (Pañales) (Leche, Cerveza) 0.6 0.75 1.2500
0 (Pan) (Leche) 0.8 1.00 1.0000
4 (Pan, Pañales) (Leche) 0.6 1.00 1.0000
9 (Pañales) (Leche) 0.8 1.00 1.0000
13 (Cerveza) (Leche) 0.6 1.00 1.0000
15 (Pañales, Cerveza) (Leche) 0.6 1.00 1.0000
1 (Leche) (Pan) 0.8 0.80 1.0000
10 (Leche) (Pañales) 0.8 0.80 1.0000
2 (Pan) (Pañales) 0.6 0.75 0.9375
3 (Pañales) (Pan) 0.6 0.75 0.9375
5 (Pan, Leche) (Pañales) 0.6 0.75 0.9375
6 (Pañales, Leche) (Pan) 0.6 0.75 0.9375
7 (Pan) (Pañales, Leche) 0.6 0.75 0.9375
8 (Pañales) (Pan, Leche) 0.6 0.75 0.9375

La confianza puede ser alta aun cuando el consecuente sea muy frecuente. Por ello, conviene interpretarla junto con el lift. Un lift mayor que uno sugiere asociación positiva; un lift cercano a uno sugiere que la regla no mejora sustancialmente lo esperado por independencia; un lift menor que uno sugiere asociación negativa.

24.11 Comparación entre FP-Growth y Apriori

Característica FP-Growth Apriori
Generación de candidatos No requerida Necesaria
Recorridos de los datos Usualmente dos recorridos principales Varios recorridos
Velocidad Eficiente en bases grandes y densas Puede ser lento por generación repetida de candidatos
Uso de memoria Puede ser alto por el FP-tree Generalmente menor, basado en listas y conteos
Implementación Más compleja Más sencilla de explicar e implementar

FP-Growth suele ser preferible cuando la base es grande y contiene muchos patrones frecuentes. Apriori puede ser útil con fines didácticos o cuando se desea una implementación directa basada en candidatos. En la práctica, la elección también depende de la densidad de las transacciones, el umbral de soporte, la memoria disponible y la necesidad de interpretar pasos intermedios.

24.12 Aplicaciones

FP-Growth es aplicable a distintos dominios donde los datos pueden representarse como conjuntos de eventos o ítems:

  • Análisis de cesta de compra: identificar productos que se compran juntos con frecuencia.
  • Sistemas de recomendación: sugerir productos, contenidos o servicios a partir de patrones de coocurrencia.
  • Análisis de comportamiento del cliente: estudiar hábitos de compra en comercio minorista o electrónico.
  • Minería de uso web: detectar rutas de navegación o secuencias de clics comunes.
  • Minería de texto: encontrar palabras, términos o frases que aparecen juntas en documentos.

En todos estos casos, los patrones frecuentes deben interpretarse con cuidado. La coocurrencia no implica causalidad. Una regla puede ser estadísticamente fuerte y, aun así, carecer de utilidad práctica si representa un patrón obvio, redundante o inducido por sesgos de captura de datos.

24.13 Ventajas y limitaciones

Entre las principales ventajas de FP-Growth se encuentran:

  • Evita la generación explícita de candidatos.
  • Reduce el número de escaneos completos de la base de datos.
  • Comprime transacciones mediante prefijos compartidos.
  • Puede extraer patrones frecuentes complejos de manera eficiente.
  • Funciona bien en bases densas donde Apriori produce demasiados candidatos.

Sus limitaciones principales son:

  • El FP-tree puede consumir mucha memoria si la base es grande y poco compresible.
  • La implementación es más compleja que Apriori.
  • La minería condicional puede ser costosa cuando existen muchos patrones frecuentes.
  • No es naturalmente incremental: cuando cambian los datos, puede requerir reconstruir el árbol.

Estas limitaciones no invalidan el método, pero sí obligan a seleccionar adecuadamente el umbral de soporte, revisar la calidad de los datos y evaluar la interpretabilidad de los patrones resultantes.

24.14 Buenas prácticas de análisis

Al aplicar FP-Growth en un proyecto real, conviene seguir una estrategia reproducible:

  1. Definir qué representa una transacción.
  2. Limpiar y normalizar los ítems.
  3. Explorar frecuencias individuales antes de minar patrones.
  4. Probar varios valores de soporte mínimo.
  5. Generar reglas solo después de revisar los itemsets frecuentes.
  6. Evaluar confianza, lift y soporte de manera conjunta.
  7. Validar los patrones con conocimiento del dominio.
  8. Documentar decisiones, umbrales y supuestos.

La etapa más importante no es ejecutar el algoritmo, sino construir una representación transaccional coherente. Por ejemplo, en minería de texto, decidir si los ítems serán palabras, lemas, n-gramas o entidades cambia completamente el significado de los patrones. En comercio electrónico, decidir si una transacción corresponde a una compra, una sesión o un usuario también modifica la interpretación del soporte.

24.15 Conclusiones

FP-Growth es un algoritmo fundamental para la minería de patrones frecuentes. Su principal contribución es reemplazar la generación explícita de candidatos por una estructura compacta, el FP-tree, que permite almacenar prefijos compartidos y extraer patrones mediante bases condicionales. Esta estrategia reduce recorridos sobre la base de datos y suele mejorar el rendimiento frente a Apriori en escenarios grandes o densos.

Desde el punto de vista conceptual, FP-Growth muestra una idea central en ciencia de datos: la eficiencia no depende solo del algoritmo, sino también de la representación. Al transformar transacciones en un árbol comprimido, el problema se vuelve más manejable sin perder la información necesaria para recuperar los itemsets frecuentes.

En aplicaciones reales, el algoritmo debe acompañarse de una interpretación cuidadosa. Los patrones frecuentes son puntos de partida para formular hipótesis, diseñar recomendaciones o comprender comportamientos, pero no constituyen por sí solos evidencia causal. Por ello, la minería de asociaciones debe integrarse con análisis exploratorio, conocimiento del dominio y criterios claros de utilidad práctica.