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()
No description has been provided for this image
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 [ ]: