| 1207 | # Based on: https://gist.github.com/1423287 |
| 1208 | |
| 1209 | class Apriori(object): |
| 1210 | |
| 1211 | def __init__(self): |
| 1212 | self._candidates = [] |
| 1213 | self._support = {} |
| 1214 | |
| 1215 | def C1(self, sets): |
| 1216 | """ Returns the unique features from all sets as a list of (hashable) frozensets. |
| 1217 | """ |
| 1218 | return [frozenset([v]) for v in set(chain(*sets))] |
| 1219 | |
| 1220 | def Ck(self, sets): |
| 1221 | """ For the given sets of length k, returns combined candidate sets of length k+1. |
| 1222 | """ |
| 1223 | Ck = [] |
| 1224 | for i, s1 in enumerate(sets): |
| 1225 | for j, s2 in enumerate(sets[i+1:]): |
| 1226 | if set(list(s1)[:-1]) == set(list(s2)[:-1]): |
| 1227 | Ck.append(s1 | s2) |
| 1228 | return Ck |
| 1229 | |
| 1230 | def Lk(self, sets, candidates, support=0.0): |
| 1231 | """ Prunes candidate sets whose frequency < support threshold. |
| 1232 | Returns a dictionary of (candidate set, frequency)-items. |
| 1233 | """ |
| 1234 | Lk, x = {}, 1.0 / (len(sets) or 1) # relative count |
| 1235 | for s1 in candidates: |
| 1236 | for s2 in sets: |
| 1237 | if s1.issubset(s2): |
| 1238 | Lk[s1] = s1 in Lk and Lk[s1]+x or x |
| 1239 | return dict((s, f) for s, f in Lk.items() if f >= support) |
| 1240 | |
| 1241 | def __call__(self, sets, support=0.5): |
| 1242 | """ Returns a dictionary of (set(features), frequency)-items. |
| 1243 | The given support (0.0-1.0) is the relative amount of documents |
| 1244 | in which a combination of feature must appear. |
| 1245 | """ |
| 1246 | C1 = self.C1(sets) |
| 1247 | L1 = self.Lk(sets, C1, support) |
| 1248 | self._candidates = [L1.keys()] |
| 1249 | self._support = L1 |
| 1250 | while True: |
| 1251 | # Terminate when no further extensions are found. |
| 1252 | if len(self._candidates[-1]) == 0: |
| 1253 | break |
| 1254 | # Extend frequent subsets one item at a time. |
| 1255 | Ck = self.Ck(self._candidates[-1]) |
| 1256 | Lk = self.Lk(sets, Ck, support) |
| 1257 | self._candidates.append(Lk.keys()) |
| 1258 | self._support.update(Lk) |
| 1259 | return self._support |
| 1260 | |
| 1261 | apriori = Apriori() |
| 1262 |
no outgoing calls
no test coverage detected
searching dependent graphs…