source: orange/orange/OrangeWidgets/Associate/OWAssociationRulesTreeViewer.py @ 8042:ffcb93bc9028

Revision 8042:ffcb93bc9028, 11.3 KB checked in by markotoplak, 3 years ago (diff)

Hierarchical clustering: also catch RuntimeError when importing matplotlib (or the documentation could not be built on server).

Line 
1"""
2<name>Association Rules Explorer</name>
3<description>Association rules tree viewer.</description>
4<icon>icons/AssociationRulesTreeViewer.png</icon>
5<contact>Janez Demsar (janez.demsar(@at@)fri.uni-lj.si)</contact>
6<priority>300</priority>
7"""
8from OWWidget import *
9import OWGUI, OWTools
10import sys, re
11
12
13class OWAssociationRulesTreeViewer(OWWidget):
14    measures = [("Support",    "Supp", "support"),
15                ("Confidence", "Conf", "confidence"),
16                ("Lift",       "Lift", "lift"),
17                ("Leverage",   "Lev",  "leverage"),
18                ("Strength",   "Strg", "strength"),
19                ("Coverage",   "Cov",  "coverage")]
20
21    # only the last name can be taken for settings - the first two can be translated
22    settingsList = ["treeDepth", "showWholeRules", "autoSend", "purgeAttributes", "purgeClasses"] \
23                   + ["show%s" % m[2] for m in measures]
24
25    def __init__(self,parent=None, signalManager = None):
26        OWWidget.__init__(self, parent, signalManager, "Association rules viewer")
27
28        self.inputs = [("Association Rules", orange.AssociationRules, self.arules)]
29        self.outputs = [("Association Rules", orange.AssociationRules), ("Covered Examples", ExampleTable), ("Matching Examples", ExampleTable), ("Mismatching Examples", ExampleTable)]
30
31        self.showWholeRules = 1
32        self.treeDepth = 2
33        self.autoSend = True
34        self.dataChanged = False
35        self.purgeAttributes = True
36        self.purgeClasses = True
37
38        self.nRules = self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = ""
39       
40        self.showsupport = self.showconfidence = 1
41        self.showlift = self.showleverage = self.showstrength = self.showcoverage = 0
42        self.loadSettings()
43
44#        self.grid = QGridLayout()
45#        rightUpRight = OWGUI.widgetBox(self.mainArea, box="Shown measures", orientation = self.grid)
46#        self.cbMeasures = [OWGUI.checkBox(rightUpRight, self, "show"+attr, long, callback = self.showHideColumn, addToLayout = 0) for long, short, attr in self.measures]
47#        for i, cb in enumerate(self.cbMeasures):
48#            self.grid.addWidget(cb, i % 2, i / 2)
49
50        box = OWGUI.widgetBox(self.mainArea, orientation = 0)
51        OWGUI.widgetLabel(box, "Shown measures: ")
52        self.cbMeasures = [OWGUI.checkBox(box, self, "show"+attr, long+"   ", callback = self.showHideColumn) for long, short, attr in self.measures]
53        OWGUI.rubber(box)
54
55        self.treeRules = QTreeWidget(self.mainArea)
56        self.mainArea.layout().addWidget(self.treeRules)
57        self.treeRules.setSelectionMode (QTreeWidget.ExtendedSelection)
58        self.treeRules.setHeaderLabels(["Rules"] + [m[1] for m in self.measures])
59        self.treeRules.setAllColumnsShowFocus ( 1)
60        self.treeRules.setAlternatingRowColors(1) 
61        self.showHideColumn()
62        self.connect(self.treeRules,SIGNAL("itemSelectionChanged()"),self. selectionChanged)
63
64        box = OWGUI.widgetBox(self.controlArea, "Info", addSpace = True)
65        OWGUI.label(box, self, "Number of rules: %(nRules)s")
66        OWGUI.label(box, self, "Selected rules: %(nSelectedRules)s")
67        OWGUI.label(box, self, "Selected examples: %(nSelectedExamples)s")
68        ibox = OWGUI.indentedBox(box)
69        OWGUI.label(ibox, self, "... matching: %(nMatchingExamples)s")
70        OWGUI.label(ibox, self, "... mismatching: %(nMismatchingExamples)s")
71
72        box = OWGUI.widgetBox(self.controlArea, "Options", addSpace = True)
73        OWGUI.spin(box, self, "treeDepth", label = "Tree depth", min = 0, max = 10, step = 1, callback = self.displayRules, callbackOnReturn = True)
74        OWGUI.separator(box)
75        OWGUI.checkBox(box, self, "showWholeRules", "Display whole rules", callback = self.setWholeRules)
76
77        OWGUI.rubber(self.controlArea)
78
79        boxSettings = OWGUI.widgetBox(self.controlArea, 'Send selection')
80        OWGUI.checkBox(boxSettings, self, "purgeAttributes", "Purge attribute values/attributes", box=None, callback=self.purgeChanged)
81        self.purgeClassesCB = OWGUI.checkBox(OWGUI.indentedBox(boxSettings), self, "purgeClasses", "Purge class attribute", callback=self.purgeChanged)
82        if not self.purgeAttributes:
83            self.purgeClassesCB.setEnabled(False)
84            self.oldPurgeClasses = False
85
86        cbSendAuto = OWGUI.checkBox(boxSettings, self, "autoSend", "Send immediately", box=None)
87        btnUpdate = OWGUI.button(boxSettings, self, "Send", self.sendData, default=True)
88        OWGUI.setStopper(self, btnUpdate, cbSendAuto, "dataChanged", self.sendData)
89       
90        self.rules = None
91
92    def sendReport(self):
93        import OWReport
94        self.reportSettings("Rule statistics",
95                            [("Number of rules", self.nRules),
96                             ("Selected rules", self.nSelectedRules),
97                             ("Examples covered by selected rules' precondition", self.nSelectedExamples),
98                             ("Matching examples", self.nMatchingExamples),
99                             ("Mismatching examples", self.nMismatchingExamples)
100                             ])
101        self.reportSection("Rules")
102        self.reportRaw(OWReport.reportTree(self.treeRules))
103
104    def setWholeRules(self, node = None):
105        if not node:
106            for i in range(self.treeRules.topLevelItemCount()):
107                self.setWholeRules(self.treeRules.topLevelItem(i))
108        else:
109            t = getattr(node, self.showWholeRules and "wholeRule" or "remainder", "")
110            if t:
111                node.setText(0, t)
112            for i in range(node.childCount()):
113                self.setWholeRules(node.child(i))
114
115
116    def showHideColumn(self):
117        for i, cb in enumerate(self.cbMeasures):
118            (cb.isChecked() and self.treeRules.showColumn or self.treeRules.hideColumn)(i+1)
119        for i in range(1+len(self.measures)):
120            self.treeRules.setColumnWidth(i, i and 50 or 300)
121
122
123    def displayRules(self):
124        self.treeRules.clear()
125        self.buildLayer(None, self.rules, self.treeDepth)
126
127
128    def buildLayer(self, parent, rulesLC, n, startOfRule = ""):
129        if n==0:
130            self.printRules(parent, rulesLC, startOfRule)
131        elif n>0:
132            children = set()
133            for rule in rulesLC:
134                children.update(rule[0])
135            for childText in children:
136                item = QTreeWidgetItem(parent or self.treeRules, [childText])
137                rules2 = []
138                newStartOfRule = startOfRule + childText + "  " 
139                for rule in rulesLC:
140                    if childText in rule[0]:
141                        if len(rule[0])==1:
142                            self.printRules(item, [(set(),) + rule[1:]], newStartOfRule)
143                        else:
144                            rules2.append((rule[0].difference([childText]),) + rule[1:])
145                self.buildLayer(item, rules2, n-1, newStartOfRule)
146
147
148    def printRules(self, parent, rulesLC, startOfRule):
149        for rule in rulesLC:
150            restOfRule = "  ".join(rule[0])
151            remainder = restOfRule+"  ->   "+rule[1]
152            wholeRule = startOfRule + remainder
153            item = QTreeWidgetItem(parent,   [self.showWholeRules and wholeRule or remainder]
154                                           + [str(%.3f  ' % v) for v in rule[2]])
155            item.remainder = remainder
156            item.wholeRule = wholeRule
157            item.ruleId = rule[3]
158
159    def gatherRules(self, node, ids):
160        if hasattr(node, "ruleId"):
161            ids.add(node.ruleId)
162        for i in range(node.childCount()):
163            self.gatherRules(node.child(i), ids)
164
165    def purgeChanged(self):
166        if self.purgeAttributes:
167            if not self.purgeClassesCB.isEnabled():
168                self.purgeClassesCB.setEnabled(True)
169                self.purgeClasses = self.oldPurgeClasses
170        else:
171            if self.purgeClassesCB.isEnabled():
172                self.purgeClassesCB.setEnabled(False)
173                self.oldPurgeClasses = self.purgeClasses
174                self.purgeClasses = False
175   
176    def selectionChanged(self):
177        ids = set()
178        for node in self.treeRules.selectedItems():
179            self.gatherRules(node, ids)
180        self.selectedRules = orange.AssociationRules([self.origRules[id] for id in ids])
181        leftids = set()
182        bothids = set()
183        for rule in self.selectedRules:
184            leftids.update(rule.matchLeft)
185            bothids.update(rule.matchBoth)
186        self.leftids = list(leftids)
187        self.bothids = list(bothids)
188        self.misids = list(leftids - bothids)
189        self.setInfo()
190        self.sendIf()
191
192    def sendIf(self):
193        if self.autoSend:
194            self.sendData()
195        else:
196            self.dataChanged = True
197           
198    def sendData(self):
199        self.dataChanged = False
200        self.send("Association Rules", self.selectedRules)
201        if self.selectedRules:
202            examples = self.selectedRules[0].examples
203
204            coveredExamples = examples.getitemsref(self.leftids)
205            matchingExamples = examples.getitemsref(self.bothids)
206            mismatchingExamples = examples.getitemsref(self.misids)
207           
208            if self.purgeAttributes or self.purgeClasses:
209                coveredExamples = OWTools.domainPurger(coveredExamples, self.purgeClasses)
210                matchingExamples = OWTools.domainPurger(matchingExamples, self.purgeClasses)
211                mismatchingExamples = OWTools.domainPurger(mismatchingExamples, self.purgeClasses)
212        else:
213            coveredExamples = matchingExamples = mismatchingExamples = None
214
215        self.send("Covered Examples", coveredExamples)
216        self.send("Matching Examples", matchingExamples)
217        self.send("Mismatching Examples", mismatchingExamples)
218       
219
220    def setInfo(self):
221        if self.origRules:
222            self.nRules = len(self.rules)
223            if self.selectedRules:
224                self.nSelectedRules = len(self.selectedRules)
225                self.nSelectedExamples = len(self.leftids)
226                self.nMatchingExamples = len(self.bothids)
227                self.nMismatchingExamples = len(self.misids)
228            else:
229                self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = ""
230        else:
231            self.nRules = self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = ""
232           
233
234    def arules(self,arules):
235        self.origRules = arules
236        self.rules=[(set(str(val.variable.name) + (val.varType and "=" + str(val) or "") for val in rule.left if not val.isSpecial()),
237                     "  ".join(str(val.variable.name) + (val.varType and "=" + str(val) or "") for val in rule.right if not val.isSpecial()),
238                     (rule.support, rule.confidence, rule.lift, rule.leverage, rule.strength, rule.coverage),
239                     id
240                     )
241                    for id, rule in enumerate(arules or [])]
242        self.displayRules()
243        self.selectionChanged()
244
245if __name__=="__main__":
246    a=QApplication(sys.argv)
247    ow=OWAssociationRulesTreeViewer()
248
249    #dataset = orange.ExampleTable('..\\..\\doc\\datasets\\car.tab')
250    dataset = orange.ExampleTable(r"E:\Development\Orange Datasets\UCI\zoo.tab")
251    rules=orange.AssociationRulesInducer(dataset, support = 0.5, maxItemSets=10000)
252    ow.arules(rules)
253
254    ow.show()
255    a.exec_()
256    ow.saveSettings()
Note: See TracBrowser for help on using the repository browser.