Skip to content

Commit eca4fdb

Browse files
committed
Fix: Apriori algorithm line lengths and type hints for ruff
1 parent 68a201c commit eca4fdb

File tree

1 file changed

+38
-43
lines changed

1 file changed

+38
-43
lines changed

machine_learning/apriori_algorithm.py

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,14 @@
1010

1111
from collections import defaultdict
1212
from itertools import combinations
13-
from typing import List, Dict, Tuple, Set
1413

1514

16-
def load_data() -> List[List[str]]:
15+
def load_data() -> list[list[str]]:
1716
"""
1817
Returns a sample transaction dataset.
1918
20-
>>> data = load_data()
21-
>>> len(data)
22-
4
23-
>>> 'milk' in data[0]
24-
True
19+
>>> load_data()
20+
[['milk'], ['milk', 'butter'], ['milk', 'bread'], ['milk', 'bread', 'chips']]
2521
"""
2622
return [["milk"], ["milk", "butter"], ["milk", "bread"], ["milk", "bread", "chips"]]
2723

@@ -31,17 +27,17 @@ class Apriori:
3127

3228
def __init__(
3329
self,
34-
transactions: List[List[str]],
30+
transactions: list[list[str]],
3531
min_support: float = 0.25,
3632
min_confidence: float = 0.5,
3733
min_lift: float = 1.0,
3834
) -> None:
39-
self.transactions: List[Set[str]] = [set(t) for t in transactions]
35+
self.transactions: list[set[str]] = [set(t) for t in transactions]
4036
self.min_support: float = min_support
4137
self.min_confidence: float = min_confidence
4238
self.min_lift: float = min_lift
43-
self.itemsets: List[Dict[frozenset, float]] = []
44-
self.rules: List[Tuple[frozenset, frozenset, float, float]] = []
39+
self.itemsets: list[dict[frozenset, float]] = []
40+
self.rules: list[tuple[frozenset, frozenset, float, float]] = []
4541

4642
self.find_frequent_itemsets()
4743
self.generate_association_rules()
@@ -54,34 +50,36 @@ def _get_support(self, itemset: frozenset) -> float:
5450

5551
def confidence(self, antecedent: frozenset, consequent: frozenset) -> float:
5652
"""Calculate confidence of a rule A -> B."""
57-
support_antecedent: float = self._get_support(antecedent)
58-
support_both: float = self._get_support(antecedent | consequent)
53+
support_antecedent = self._get_support(antecedent)
54+
support_both = self._get_support(antecedent | consequent)
5955
return support_both / support_antecedent if support_antecedent > 0 else 0.0
6056

6157
def lift(self, antecedent: frozenset, consequent: frozenset) -> float:
6258
"""Calculate lift of a rule A -> B."""
63-
support_consequent: float = self._get_support(consequent)
64-
conf: float = self.confidence(antecedent, consequent)
59+
support_consequent = self._get_support(consequent)
60+
conf = self.confidence(antecedent, consequent)
6561
return conf / support_consequent if support_consequent > 0 else 0.0
6662

67-
def find_frequent_itemsets(self) -> List[Dict[frozenset, float]]:
63+
def find_frequent_itemsets(self) -> list[dict[frozenset, float]]:
6864
"""Generate all frequent itemsets."""
69-
item_counts: Dict[frozenset, int] = defaultdict(int)
65+
item_counts: dict[frozenset, int] = defaultdict(int)
7066
for t in self.transactions:
7167
for item in t:
7268
item_counts[frozenset([item])] += 1
7369

7470
total: int = len(self.transactions)
75-
current_itemsets: Dict[frozenset, float] = {
76-
k: v / total for k, v in item_counts.items() if v / total >= self.min_support
71+
current_itemsets: dict[frozenset, float] = {
72+
k: v / total
73+
for k, v in item_counts.items()
74+
if v / total >= self.min_support
7775
}
7876
if current_itemsets:
7977
self.itemsets.append(current_itemsets)
8078

8179
k: int = 2
8280
while current_itemsets:
83-
candidates: Set[frozenset] = set()
84-
keys: List[frozenset] = list(current_itemsets.keys())
81+
candidates: set[frozenset] = set()
82+
keys: list[frozenset] = list(current_itemsets.keys())
8583
for i in range(len(keys)):
8684
for j in range(i + 1, len(keys)):
8785
union = keys[i] | keys[j]
@@ -91,8 +89,10 @@ def find_frequent_itemsets(self) -> List[Dict[frozenset, float]]:
9189
):
9290
candidates.add(union)
9391

94-
freq_candidates: Dict[frozenset, float] = {
95-
c: self._get_support(c) for c in candidates if self._get_support(c) >= self.min_support
92+
freq_candidates: dict[frozenset, float] = {
93+
c: self._get_support(c)
94+
for c in candidates
95+
if self._get_support(c) >= self.min_support
9696
}
9797
if not freq_candidates:
9898
break
@@ -103,26 +103,24 @@ def find_frequent_itemsets(self) -> List[Dict[frozenset, float]]:
103103

104104
return self.itemsets
105105

106-
def generate_association_rules(self) -> List[Tuple[frozenset, frozenset, float, float]]:
106+
def generate_association_rules(
107+
self,
108+
) -> list[tuple[frozenset, frozenset, float, float]]:
107109
"""Generate association rules with min confidence and lift."""
108110
for level in self.itemsets:
109111
for itemset in level:
110112
if len(itemset) < 2:
111113
continue
112114
for i in range(1, len(itemset)):
113115
for antecedent in combinations(itemset, i):
114-
antecedent_set: frozenset = frozenset(antecedent)
115-
consequent_set: frozenset = itemset - antecedent_set
116-
conf: float = self.confidence(antecedent_set, consequent_set)
117-
lft: float = self.lift(antecedent_set, consequent_set)
118-
rule: Tuple[frozenset, frozenset, float, float] = (
119-
antecedent_set,
120-
consequent_set,
121-
conf,
122-
lft,
123-
)
124-
if rule not in self.rules and conf >= self.min_confidence and lft >= self.min_lift:
125-
self.rules.append(rule)
116+
antecedent_set = frozenset(antecedent)
117+
consequent_set = itemset - antecedent_set
118+
conf = self.confidence(antecedent_set, consequent_set)
119+
lft = self.lift(antecedent_set, consequent_set)
120+
if conf >= self.min_confidence and lft >= self.min_lift:
121+
self.rules.append(
122+
(antecedent_set, consequent_set, conf, lft)
123+
)
126124
return self.rules
127125

128126

@@ -131,10 +129,8 @@ def generate_association_rules(self) -> List[Tuple[frozenset, frozenset, float,
131129

132130
doctest.testmod()
133131

134-
transactions: List[List[str]] = load_data()
135-
model: Apriori = Apriori(
136-
transactions, min_support=0.25, min_confidence=0.1, min_lift=0.0
137-
)
132+
transactions = load_data()
133+
model = Apriori(transactions, min_support=0.25, min_confidence=0.1, min_lift=0.0)
138134

139135
print("Frequent itemsets:")
140136
for level in model.itemsets:
@@ -143,8 +139,7 @@ def generate_association_rules(self) -> List[Tuple[frozenset, frozenset, float,
143139

144140
print("\nAssociation Rules:")
145141
for rule in model.rules:
146-
antecedent, consequent, conf, lift_value = rule
142+
antecedent, consequent, conf, lift = rule
147143
print(
148-
f"{set(antecedent)} -> {set(consequent)}, "
149-
f"conf={conf:.2f}, lift={lift_value:.2f}"
144+
f"{set(antecedent)} -> {set(consequent)}, conf={conf:.2f}, lift={lift:.2f}"
150145
)

0 commit comments

Comments
 (0)