In [ ]:
#todays task
#Learn how to use python t do basket analysis (association rule mining)
In [ ]:
pip install --upgrade jupyter_client
Requirement already satisfied: jupyter_client in /usr/local/lib/python3.12/dist-packages (8.6.3) Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /usr/local/lib/python3.12/dist-packages (from jupyter_client) (5.8.1) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from jupyter_client) (2.9.0.post0) Requirement already satisfied: pyzmq>=23.0 in /usr/local/lib/python3.12/dist-packages (from jupyter_client) (26.2.1) Requirement already satisfied: tornado>=6.2 in /usr/local/lib/python3.12/dist-packages (from jupyter_client) (6.4.2) Requirement already satisfied: traitlets>=5.3 in /usr/local/lib/python3.12/dist-packages (from jupyter_client) (5.7.1) Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.12/dist-packages (from jupyter-core!=5.0.*,>=4.12->jupyter_client) (4.4.0) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->jupyter_client) (1.17.0)
In [ ]:
pip install mlxtend
Requirement already satisfied: mlxtend in /usr/local/lib/python3.12/dist-packages (0.23.4) Requirement already satisfied: scipy>=1.2.1 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (1.16.2) Requirement already satisfied: numpy>=1.16.2 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (2.0.2) Requirement already satisfied: pandas>=0.24.2 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (2.2.2) Requirement already satisfied: scikit-learn>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (1.6.1) Requirement already satisfied: matplotlib>=3.0.0 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (3.10.0) Requirement already satisfied: joblib>=0.13.2 in /usr/local/lib/python3.12/dist-packages (from mlxtend) (1.5.2) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (1.3.3) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (4.60.0) Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (1.4.9) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (25.0) Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (11.3.0) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (3.2.4) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.12/dist-packages (from matplotlib>=3.0.0->mlxtend) (2.9.0.post0) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas>=0.24.2->mlxtend) (2025.2) Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas>=0.24.2->mlxtend) (2025.2) Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.12/dist-packages (from scikit-learn>=1.3.1->mlxtend) (3.6.0) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.7->matplotlib>=3.0.0->mlxtend) (1.17.0)
In [ ]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori, association_rules
In [ ]:
df= pd.read_csv('grocery_data.csv')
df.head()
Out[ ]:
| customer_ID | itemDescription | |
|---|---|---|
| 0 | 1808 | tropical fruit |
| 1 | 2552 | whole milk |
| 2 | 2300 | pip fruit |
| 3 | 1187 | other vegetables |
| 4 | 3037 | whole milk |
In [ ]:
#top 5 items sold
top5= df['itemDescription'].value_counts().head(5)
top5
Out[ ]:
| count | |
|---|---|
| itemDescription | |
| whole milk | 2502 |
| other vegetables | 1898 |
| rolls/buns | 1716 |
| soda | 1514 |
| yogurt | 1334 |
In [ ]:
plt.figure(figsize=(7,3))
sns.barplot(x=top5.index, y=top5.values, palette='viridis', hue= top5.index)
plt.title('Top 5 items sold')
plt.xlabel('Items')
plt.show()
In [ ]:
# data preprocessing: turn the items into transactions
basket= df.groupby('customer_ID')['itemDescription'].apply(list)
basket_df=basket.reset_index()
basket_df.head()
Out[ ]:
| customer_ID | itemDescription | |
|---|---|---|
| 0 | 1000 | [soda, canned beer, sausage, sausage, whole mi... |
| 1 | 1001 | [frankfurter, frankfurter, beef, sausage, whol... |
| 2 | 1002 | [tropical fruit, butter milk, butter, frozen v... |
| 3 | 1003 | [sausage, root vegetables, rolls/buns, deterge... |
| 4 | 1004 | [other vegetables, pip fruit, root vegetables,... |
In [ ]:
te= TransactionEncoder()
onehot = te.fit_transform(basket_df['itemDescription'])
new_df= pd.DataFrame(onehot, columns=te.columns_, index= basket_df['customer_ID'])
new_df.head()
Out[ ]:
| Instant food products | UHT-milk | abrasive cleaner | artif. sweetener | baby cosmetics | bags | baking powder | bathroom cleaner | beef | berries | beverages | bottled beer | bottled water | brandy | brown bread | butter | butter milk | cake bar | candles | candy | canned beer | canned fish | canned fruit | canned vegetables | cat food | cereals | chewing gum | chicken | chocolate | chocolate marshmallow | citrus fruit | cleaner | cling film/bags | cocoa drinks | coffee | condensed milk | cooking chocolate | cookware | cream | cream cheese | ... | salt | salty snack | sauces | sausage | seasonal products | semi-finished bread | shopping bags | skin care | sliced cheese | snack products | soap | soda | soft cheese | softener | soups | sparkling wine | specialty bar | specialty cheese | specialty chocolate | specialty fat | specialty vegetables | spices | spread cheese | sugar | sweet spreads | syrup | tea | tidbits | toilet cleaner | tropical fruit | turkey | vinegar | waffles | whipped/sour cream | whisky | white bread | white wine | whole milk | yogurt | zwieback | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| customer_ID | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1000 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | ... | False | True | False | True | False | True | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | False |
| 1001 | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | True | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | False | True | False | False |
| 1002 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | True | False | False | False | False | False | True | False | False | False | False | False | False | False | True | False | False |
| 1003 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | ... | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| 1004 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | True | False | False | False | True | False | False | False | False | False | False | False | ... | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | True | False | False |
5 rows × 167 columns
In [ ]:
# Apriori
freq = apriori(new_df, min_support=0.1, use_colnames=True)
freq
Out[ ]:
| support | itemsets | |
|---|---|---|
| 0 | 0.119548 | (beef) |
| 1 | 0.158799 | (bottled beer) |
| 2 | 0.213699 | (bottled water) |
| 3 | 0.135967 | (brown bread) |
| 4 | 0.126475 | (butter) |
| 5 | 0.165213 | (canned beer) |
| 6 | 0.100564 | (chicken) |
| 7 | 0.185480 | (citrus fruit) |
| 8 | 0.114931 | (coffee) |
| 9 | 0.120831 | (curd) |
| 10 | 0.133145 | (domestic eggs) |
| 11 | 0.137506 | (frankfurter) |
| 12 | 0.102617 | (frozen vegetables) |
| 13 | 0.124936 | (fruit/vegetable juice) |
| 14 | 0.116983 | (margarine) |
| 15 | 0.139815 | (newspapers) |
| 16 | 0.376603 | (other vegetables) |
| 17 | 0.177527 | (pastry) |
| 18 | 0.170600 | (pip fruit) |
| 19 | 0.132376 | (pork) |
| 20 | 0.349666 | (rolls/buns) |
| 21 | 0.230631 | (root vegetables) |
| 22 | 0.206003 | (sausage) |
| 23 | 0.168291 | (shopping bags) |
| 24 | 0.313494 | (soda) |
| 25 | 0.233710 | (tropical fruit) |
| 26 | 0.154695 | (whipped/sour cream) |
| 27 | 0.458184 | (whole milk) |
| 28 | 0.282966 | (yogurt) |
| 29 | 0.112365 | (bottled water, whole milk) |
| 30 | 0.146742 | (other vegetables, rolls/buns) |
| 31 | 0.124166 | (other vegetables, soda) |
| 32 | 0.191380 | (other vegetables, whole milk) |
| 33 | 0.120318 | (other vegetables, yogurt) |
| 34 | 0.119805 | (rolls/buns, soda) |
| 35 | 0.178553 | (rolls/buns, whole milk) |
| 36 | 0.111339 | (yogurt, rolls/buns) |
| 37 | 0.113135 | (root vegetables, whole milk) |
| 38 | 0.106978 | (sausage, whole milk) |
| 39 | 0.151103 | (soda, whole milk) |
| 40 | 0.116470 | (tropical fruit, whole milk) |
| 41 | 0.150590 | (yogurt, whole milk) |
In [ ]:
rules= association_rules(freq, metric='confidence', min_threshold=0.2)
rules
#consequents is what item is most likely to be bought in association with the antecedents
#anything with a lift higher than 1.0 is likely to happen
Out[ ]:
| antecedents | consequents | antecedent support | consequent support | support | confidence | lift | representativity | leverage | conviction | zhangs_metric | jaccard | certainty | kulczynski | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | (bottled water) | (whole milk) | 0.213699 | 0.458184 | 0.112365 | 0.525810 | 1.147597 | 1.0 | 0.014452 | 1.142615 | 0.163569 | 0.200825 | 0.124815 | 0.385526 |
| 1 | (whole milk) | (bottled water) | 0.458184 | 0.213699 | 0.112365 | 0.245241 | 1.147597 | 1.0 | 0.014452 | 1.041790 | 0.237376 | 0.200825 | 0.040114 | 0.385526 |
| 2 | (other vegetables) | (rolls/buns) | 0.376603 | 0.349666 | 0.146742 | 0.389646 | 1.114335 | 1.0 | 0.015056 | 1.065502 | 0.164589 | 0.253209 | 0.061475 | 0.404654 |
| 3 | (rolls/buns) | (other vegetables) | 0.349666 | 0.376603 | 0.146742 | 0.419663 | 1.114335 | 1.0 | 0.015056 | 1.074197 | 0.157772 | 0.253209 | 0.069072 | 0.404654 |
| 4 | (other vegetables) | (soda) | 0.376603 | 0.313494 | 0.124166 | 0.329700 | 1.051695 | 1.0 | 0.006103 | 1.024178 | 0.078849 | 0.219402 | 0.023607 | 0.362886 |
| 5 | (soda) | (other vegetables) | 0.313494 | 0.376603 | 0.124166 | 0.396072 | 1.051695 | 1.0 | 0.006103 | 1.032237 | 0.071601 | 0.219402 | 0.031230 | 0.362886 |
| 6 | (other vegetables) | (whole milk) | 0.376603 | 0.458184 | 0.191380 | 0.508174 | 1.109106 | 1.0 | 0.018827 | 1.101643 | 0.157802 | 0.297448 | 0.092265 | 0.462934 |
| 7 | (whole milk) | (other vegetables) | 0.458184 | 0.376603 | 0.191380 | 0.417693 | 1.109106 | 1.0 | 0.018827 | 1.070564 | 0.181562 | 0.297448 | 0.065913 | 0.462934 |
| 8 | (other vegetables) | (yogurt) | 0.376603 | 0.282966 | 0.120318 | 0.319482 | 1.129050 | 1.0 | 0.013752 | 1.053660 | 0.183350 | 0.223121 | 0.050927 | 0.372343 |
| 9 | (yogurt) | (other vegetables) | 0.282966 | 0.376603 | 0.120318 | 0.425204 | 1.129050 | 1.0 | 0.013752 | 1.084553 | 0.159406 | 0.223121 | 0.077961 | 0.372343 |
| 10 | (rolls/buns) | (soda) | 0.349666 | 0.313494 | 0.119805 | 0.342627 | 1.092928 | 1.0 | 0.010187 | 1.044316 | 0.130743 | 0.220491 | 0.042436 | 0.362393 |
| 11 | (soda) | (rolls/buns) | 0.313494 | 0.349666 | 0.119805 | 0.382160 | 1.092928 | 1.0 | 0.010187 | 1.052593 | 0.123855 | 0.220491 | 0.049965 | 0.362393 |
| 12 | (rolls/buns) | (whole milk) | 0.349666 | 0.458184 | 0.178553 | 0.510638 | 1.114484 | 1.0 | 0.018342 | 1.107190 | 0.157955 | 0.283734 | 0.096813 | 0.450168 |
| 13 | (whole milk) | (rolls/buns) | 0.458184 | 0.349666 | 0.178553 | 0.389698 | 1.114484 | 1.0 | 0.018342 | 1.065592 | 0.189591 | 0.283734 | 0.061555 | 0.450168 |
| 14 | (yogurt) | (rolls/buns) | 0.282966 | 0.349666 | 0.111339 | 0.393472 | 1.125279 | 1.0 | 0.012396 | 1.072224 | 0.155267 | 0.213583 | 0.067359 | 0.355944 |
| 15 | (rolls/buns) | (yogurt) | 0.349666 | 0.282966 | 0.111339 | 0.318415 | 1.125279 | 1.0 | 0.012396 | 1.052011 | 0.171191 | 0.213583 | 0.049439 | 0.355944 |
| 16 | (root vegetables) | (whole milk) | 0.230631 | 0.458184 | 0.113135 | 0.490545 | 1.070630 | 1.0 | 0.007464 | 1.063522 | 0.085746 | 0.196524 | 0.059728 | 0.368733 |
| 17 | (whole milk) | (root vegetables) | 0.458184 | 0.230631 | 0.113135 | 0.246920 | 1.070630 | 1.0 | 0.007464 | 1.021630 | 0.121758 | 0.196524 | 0.021172 | 0.368733 |
| 18 | (sausage) | (whole milk) | 0.206003 | 0.458184 | 0.106978 | 0.519303 | 1.133394 | 1.0 | 0.012591 | 1.127146 | 0.148230 | 0.191989 | 0.112804 | 0.376393 |
| 19 | (whole milk) | (sausage) | 0.458184 | 0.206003 | 0.106978 | 0.233483 | 1.133394 | 1.0 | 0.012591 | 1.035850 | 0.217222 | 0.191989 | 0.034609 | 0.376393 |
| 20 | (soda) | (whole milk) | 0.313494 | 0.458184 | 0.151103 | 0.481997 | 1.051973 | 1.0 | 0.007465 | 1.045971 | 0.071966 | 0.243489 | 0.043950 | 0.405892 |
| 21 | (whole milk) | (soda) | 0.458184 | 0.313494 | 0.151103 | 0.329787 | 1.051973 | 1.0 | 0.007465 | 1.024310 | 0.091184 | 0.243489 | 0.023733 | 0.405892 |
| 22 | (tropical fruit) | (whole milk) | 0.233710 | 0.458184 | 0.116470 | 0.498353 | 1.087672 | 1.0 | 0.009388 | 1.080076 | 0.105189 | 0.202407 | 0.074139 | 0.376276 |
| 23 | (whole milk) | (tropical fruit) | 0.458184 | 0.233710 | 0.116470 | 0.254199 | 1.087672 | 1.0 | 0.009388 | 1.027473 | 0.148768 | 0.202407 | 0.026739 | 0.376276 |
| 24 | (yogurt) | (whole milk) | 0.282966 | 0.458184 | 0.150590 | 0.532185 | 1.161510 | 1.0 | 0.020940 | 1.158185 | 0.193926 | 0.254996 | 0.136580 | 0.430426 |
| 25 | (whole milk) | (yogurt) | 0.458184 | 0.282966 | 0.150590 | 0.328667 | 1.161510 | 1.0 | 0.020940 | 1.068076 | 0.256640 | 0.254996 | 0.063737 | 0.430426 |
In [ ]:
#rank by strongest to weakest
rules= rules[rules['lift']>1.1].sort_values(by='confidence', ascending=False)
rules.head(10)[['antecedents', 'consequents', 'support', 'confidence', 'lift']]
Out[ ]:
| antecedents | consequents | support | confidence | lift | |
|---|---|---|---|---|---|
| 24 | (yogurt) | (whole milk) | 0.150590 | 0.532185 | 1.161510 |
| 0 | (bottled water) | (whole milk) | 0.112365 | 0.525810 | 1.147597 |
| 18 | (sausage) | (whole milk) | 0.106978 | 0.519303 | 1.133394 |
| 12 | (rolls/buns) | (whole milk) | 0.178553 | 0.510638 | 1.114484 |
| 6 | (other vegetables) | (whole milk) | 0.191380 | 0.508174 | 1.109106 |
| 9 | (yogurt) | (other vegetables) | 0.120318 | 0.425204 | 1.129050 |
| 3 | (rolls/buns) | (other vegetables) | 0.146742 | 0.419663 | 1.114335 |
| 7 | (whole milk) | (other vegetables) | 0.191380 | 0.417693 | 1.109106 |
| 14 | (yogurt) | (rolls/buns) | 0.111339 | 0.393472 | 1.125279 |
| 13 | (whole milk) | (rolls/buns) | 0.178553 | 0.389698 | 1.114484 |
In [ ]: