Association Rule Mining Cheat Sheet
Explains support, confidence, and lift metrics along with the Apriori and FP-Growth algorithms for discovering frequent itemsets and association rules.
Key Metrics
The three numbers every association rule is judged on.
- Support- P(A and B): fraction of all transactions containing both items
- Confidence- P(B|A): fraction of transactions with A that also contain B
- Lift- confidence(A->B) / support(B); lift > 1 means A and B co-occur more than chance
- Antecedent / consequent- "If A (antecedent) then B (consequent)" -- the left- and right-hand sides of a rule
- Frequent itemset- A set of items whose support meets a minimum threshold
Apriori Algorithm
Mine frequent itemsets and rules from one-hot encoded transactions with mlxtend.
from mlxtend.frequent_patterns import apriori, association_rules# df: one-hot encoded, rows = transactions, cols = items (True/False)frequent_itemsets = apriori(df, min_support=0.02, use_colnames=True)rules = association_rules(frequent_itemsets, metric='lift', min_threshold=1.0)rules = rules.sort_values('lift', ascending=False)print(rules[['antecedents', 'consequents', 'support', 'confidence', 'lift']].head())
FP-Growth Algorithm
Faster alternative to Apriori that avoids repeated database scans via an FP-tree.
from mlxtend.frequent_patterns import fpgrowthfrequent_itemsets = fpgrowth(df, min_support=0.02, use_colnames=True)print(frequent_itemsets.sort_values('support', ascending=False).head(10))
Common Use Cases
Where market-basket analysis shows up in practice.
- Market basket analysis- "Customers who bought X also bought Y" recommendations in retail
- Cross-selling- Bundling frequently co-purchased products in promotions
- Web usage mining- Finding sequences of pages frequently visited together
- Fraud detection- Discovering unusual co-occurring transaction patterns
Metrics Beyond Lift
Additional rule-quality measures that catch cases lift alone misses.
- Leverage- support(A∪B) - support(A)*support(B); measures absolute (not ratio) deviation from independence, penalizes rare itemsets less harshly than lift
- Conviction- (1 - support(B)) / (1 - confidence(A→B)); infinite for rules that are always true, sensitive to rule direction unlike lift
- Zhang's metric- Normalized measure in [-1, 1] that captures both positive and negative association strength symmetrically
- Certainty factor- Degree of belief change in B given A, correcting confidence for B's baseline frequency
- Jaccard / cosine of itemsets- Similarity-based measures useful when comparing itemsets of very different sizes
Closed and Maximal Frequent Itemsets
Reduce the frequent-itemset explosion by keeping only closed or maximal sets.
from mlxtend.frequent_patterns import fpgrowthitemsets = fpgrowth(df, min_support=0.01, use_colnames=True)itemsets['length'] = itemsets['itemsets'].apply(len)def is_closed(row, all_itemsets): supersets = all_itemsets[all_itemsets['itemsets'].apply(lambda s: row['itemsets'] < s)] return not any(supersets['support'] == row['support'])def is_maximal(row, all_itemsets): supersets = all_itemsets[all_itemsets['itemsets'].apply(lambda s: row['itemsets'] < s)] return supersets.emptyitemsets['closed'] = itemsets.apply(lambda r: is_closed(r, itemsets), axis=1)itemsets['maximal'] = itemsets.apply(lambda r: is_maximal(r, itemsets), axis=1)# closed itemsets: no superset shares the same support (lossless compression)# maximal itemsets: no frequent superset exists at all (most compact, lossy)
Sequential Pattern Mining (PrefixSpan)
Mine ordered patterns (e.g., page A then B then C) instead of unordered itemsets.
from prefixspan import PrefixSpan# sequences: list of lists, e.g. clickstreams per sessionsequences = [ ['home', 'search', 'product', 'cart'], ['home', 'product', 'cart', 'checkout'], ['search', 'product', 'wishlist'],]ps = PrefixSpan(sequences)top_patterns = ps.topk(10) # (support_count, pattern) pairsfrequent = ps.frequent(minsup=2) # all patterns with support >= 2
Scaling with Spark FPGrowth
Mine frequent itemsets on transaction volumes too large for mlxtend / a single machine.
from pyspark.ml.fpm import FPGrowth# transactions_df: one row per transaction, column 'items' = array<string>fpgrowth = FPGrowth(itemsCol='items', minSupport=0.01, minConfidence=0.3)model = fpgrowth.fit(transactions_df)model.freqItemsets.orderBy('freq', ascending=False).show(10)model.associationRules.orderBy('lift', ascending=False).show(10)predictions = model.transform(transactions_df) # scores new baskets against learned rules
Pitfalls at Scale
Failure modes that show up once rule mining moves beyond toy datasets.
- Rule explosion- Lowering min_support too far produces thousands of redundant rules; prune with closed/maximal itemsets or a minimum lift threshold
- Redundant rules- A rule implied by a more general rule with equal or better confidence adds no information -- filter these out
- Simpson's paradox- A rule can show positive lift overall but negative lift within every subgroup (e.g., store location) if segments aren't checked separately
- Multi-level / generalized rules- Mining across a category hierarchy (e.g., 'dairy' vs. 'whole milk') surfaces patterns invisible at a single granularity
- Temporal drift- Rules mined on last year's baskets can silently stop holding as product mix and seasonality shift
A high-lift rule with very low support is often just noise from a handful of transactions -- always check support alongside lift before acting on a rule.