Changeset 4995:92ecaa269ecf in orange


Ignore:
Timestamp:
07/18/08 23:11:29 (6 years ago)
Author:
janezd <janez.demsar@…>
Branch:
default
Convert:
8ba8e601208e6e9c8257cfe07b90ec1100f9612c
Message:
  • added lots of new features (signals with examples etc)
Location:
orange/OrangeWidgets/Associate
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Associate/OWAssociationRules.py

    r4795 r4995  
    5555                num_steps = 20 
    5656                for i in range(num_steps): 
    57                     build_support = 1 - float(i) / num_steps * (1 - self.minSupport/100.0) 
     57                    build_support = (i == num_steps-1) and self.minSupport/100. or (1 - float(i) / num_steps * (1 - self.minSupport/100.0)) 
    5858                    if self.useSparseAlgorithm: 
    59                         rules = orange.AssociationRulesSparseInducer(self.dataset, support = build_support, confidence = self.minConfidence/100.) 
     59                        rules = orange.AssociationRulesSparseInducer(self.dataset, support = build_support, confidence = self.minConfidence/100., storeExamples = True) 
    6060                    else: 
    61                         rules = orange.AssociationRulesInducer(self.dataset, support = build_support, confidence = self.minConfidence/100., classificationRules = self.classificationRules) 
     61                        rules = orange.AssociationRulesInducer(self.dataset, support = build_support, confidence = self.minConfidence/100., classificationRules = self.classificationRules, storeExamples = True) 
    6262                    if len(rules) >= self.maxRules: 
    6363                        break 
  • orange/OrangeWidgets/Associate/OWAssociationRulesTreeViewer.py

    r4795 r4995  
    11""" 
    2 <name>Association Rules Tree Viewer</name> 
     2<name>Association Rules Explorer</name> 
    33<description>Association rules tree viewer.</description> 
    44<icon>icons/AssociationRulesTreeViewer.png</icon> 
     
    88import orngOrangeFoldersQt4 
    99from OWWidget import * 
    10 import OWGUI 
     10import OWGUI, OWTools 
    1111import sys, re 
    1212 
     
    2121 
    2222    # only the last name can be taken for settings - the first two can be translated 
    23     settingsList = ["treeDepth", "showWholeRules"] + ["show%s" % m[2] for m in measures] 
     23    settingsList = ["treeDepth", "showWholeRules", "autoSend", "purgeAttributes", "purgeClasses"] \ 
     24                   + ["show%s" % m[2] for m in measures] 
    2425 
    2526    def __init__(self,parent=None, signalManager = None): 
     
    2728 
    2829        self.inputs = [("Association Rules", orange.AssociationRules, self.arules)] 
    29         self.outputs = [] 
    30  
    31         # Settings 
     30        self.outputs = [("Association Rules", orange.AssociationRules), ("Covered Examples", ExampleTable), ("Matching Examples", ExampleTable), ("Mismatching Examples", ExampleTable)] 
     31 
    3232        self.showWholeRules = 1 
    3333        self.treeDepth = 2 
    34  
     34        self.autoSend = True 
     35        self.dataChanged = False 
     36        self.purgeAttributes = True 
     37        self.purgeClasses = True 
     38 
     39        self.nRules = self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = "" 
     40         
    3541        self.showsupport = self.showconfidence = 1 
    3642        self.showlift = self.showleverage = self.showstrength = self.showcoverage = 0 
    3743        self.loadSettings() 
    3844 
    39         self.treeRules = QTreeWidget(self.mainArea)       #the rules and their properties are printed into this QListView 
     45#        self.grid = QGridLayout() 
     46#        rightUpRight = OWGUI.widgetBox(self.mainArea, box="Shown measures", orientation = self.grid) 
     47#        self.cbMeasures = [OWGUI.checkBox(rightUpRight, self, "show"+attr, long, callback = self.showHideColumn, addToLayout = 0) for long, short, attr in self.measures] 
     48#        for i, cb in enumerate(self.cbMeasures): 
     49#            self.grid.addWidget(cb, i % 2, i / 2) 
     50 
     51        box = OWGUI.widgetBox(self.mainArea, orientation = 0) 
     52        OWGUI.widgetLabel(box, "Shown measures: ") 
     53        self.cbMeasures = [OWGUI.checkBox(box, self, "show"+attr, long+"   ", callback = self.showHideColumn) for long, short, attr in self.measures] 
     54        OWGUI.rubber(box) 
     55 
     56        self.treeRules = QTreeWidget(self.mainArea) 
    4057        self.mainArea.layout().addWidget(self.treeRules) 
    41 #        self.treeRules.setMultiSelection (1)              #allow multiple selection 
     58        self.treeRules.setSelectionMode (QTreeWidget.ExtendedSelection) 
     59        self.treeRules.setHeaderLabels(["Rules"] + [m[1] for m in self.measures]) 
    4260        self.treeRules.setAllColumnsShowFocus ( 1) 
    43  
    44         columnTexts = ["Rules"] 
    45  
    46         mbox = OWGUI.widgetBox(self.controlArea, "Shown measures") 
    47         self.cbMeasures = [] 
    48         for long, short, attr in self.measures: 
    49             self.cbMeasures.append(OWGUI.checkBox(mbox, self, "show"+attr, long, callback = self.showHideColumn)) 
    50             columnTexts.append(short) 
    51         self.treeRules.setHeaderLabels(columnTexts) 
    52  
    53         OWGUI.separator(self.controlArea) 
    54  
    55         box = OWGUI.widgetBox(self.controlArea, "Options") 
    56         OWGUI.widgetLabel(box, "Tree depth") 
    57         OWGUI.hSlider(box, self, "treeDepth", minValue = 0, maxValue = 10, step = 1, callback = self.displayRules) 
     61        self.treeRules.setAlternatingRowColors(1)  
     62        self.showHideColumn() 
     63        self.connect(self.treeRules,SIGNAL("itemSelectionChanged()"),self. selectionChanged) 
     64 
     65        box = OWGUI.widgetBox(self.controlArea, "Info", addSpace = True) 
     66        OWGUI.label(box, self, "Number of rules: %(nRules)s") 
     67        OWGUI.label(box, self, "Selected rules: %(nSelectedRules)s") 
     68        OWGUI.label(box, self, "Selected examples: %(nSelectedExamples)s") 
     69        ibox = OWGUI.indentedBox(box) 
     70        OWGUI.label(ibox, self, "... matching: %(nMatchingExamples)s") 
     71        OWGUI.label(ibox, self, "... mismatching: %(nMismatchingExamples)s") 
     72 
     73        box = OWGUI.widgetBox(self.controlArea, "Options", addSpace = True) 
     74        OWGUI.spin(box, self, "treeDepth", label = "Tree depth", min = 0, max = 10, step = 1, callback = self.displayRules, callbackOnReturn = True) 
    5875        OWGUI.separator(box) 
    5976        OWGUI.checkBox(box, self, "showWholeRules", "Display whole rules", callback = self.setWholeRules) 
    6077 
    6178        OWGUI.rubber(self.controlArea) 
     79 
     80        boxSettings = OWGUI.widgetBox(self.controlArea, 'Send selection') 
     81        OWGUI.checkBox(boxSettings, self, "purgeAttributes", "Purge attribute values/attributes", box=None, callback=self.purgeChanged) 
     82        self.purgeClassesCB = OWGUI.checkBox(OWGUI.indentedBox(boxSettings), self, "purgeClasses", "Purge class attribute", callback=self.purgeChanged) 
     83        if not self.purgeAttributes: 
     84            self.purgeClassesCB.setEnabled(False) 
     85            self.oldPurgeClasses = False 
     86 
     87        cbSendAuto = OWGUI.checkBox(boxSettings, self, "autoSend", "Send immediately", box=None) 
     88        btnUpdate = OWGUI.button(boxSettings, self, "Send", self.sendData) 
     89        OWGUI.setStopper(self, btnUpdate, cbSendAuto, "dataChanged", self.sendData) 
     90         
    6291        self.rules = None 
    6392 
    6493 
    65     def setWholeRules(self): 
    66         d = self.showWholeRules and 1 or 2 
    67         for line in self.wrlist: 
    68             try: 
    69                 line[0].setText(0,line[d]) 
    70             except: 
    71                 print line 
     94    def setWholeRules(self, node = None): 
     95        if not node: 
     96            for i in range(self.treeRules.topLevelItemCount()): 
     97                self.setWholeRules(self.treeRules.topLevelItem(i)) 
     98        else: 
     99            t = getattr(node, self.showWholeRules and "wholeRule" or "remainder", "") 
     100            if t: 
     101                node.setText(0, t) 
     102            for i in range(node.childCount()): 
     103                self.setWholeRules(node.child(i)) 
    72104 
    73105 
    74106    def showHideColumn(self): 
    75107        for i, cb in enumerate(self.cbMeasures): 
    76             self.treeRules.setColumnWidth(i+1, cb.isChecked() and 40) 
     108            (cb.isChecked() and self.treeRules.showColumn or self.treeRules.hideColumn)(i+1) 
     109        for i in range(1+len(self.measures)): 
     110            self.treeRules.setColumnWidth(i, i and 50 or 300) 
     111 
    77112 
    78113    def displayRules(self): 
    79         """ Display rules as a tree. """ 
    80114        self.treeRules.clear() 
    81         self.wrlist = [] 
    82         if self.rules: 
    83             self.rulesLC=[] 
    84             for rule in self.rules:                 # local copy of rules [[antecedens1,antecedens2,...], [consequens, support,...]] (without measures) 
    85                 values = filter(lambda val: not val.isSpecial(), rule.left) 
    86  
    87                 antecedens = [] 
    88                 for x in values: 
    89                     if x.varType: 
    90                         antecedens.append(str(x.variable.name) + "=" + str(x)) 
    91                     else: 
    92                         antecedens.append(str(x.variable.name)) 
    93  
    94                 values = filter(lambda val: not val.isSpecial(), rule.right) 
    95  
    96                 kons="" 
    97                 for x in values: 
    98                     if x.varType: 
    99                         kons=kons + str(x.variable.name) + "=" + str(x) + "  " 
    100                     else: 
    101                         kons=kons + str(x.variable.name) + "  " 
    102  
    103                 self.rulesLC.append([antecedens, [kons, rule.support, rule.confidence, rule.lift, rule.leverage, rule.strength, rule.coverage]]) 
    104  
    105             self.updateTree() 
    106             self.removeSingleGrouping()        # if there is only 1 rule behind a +, the rule is 
    107             self.setWholeRules() 
    108             self.showHideColumn() 
    109             self.item0.setExpanded(1)                        # display the rules 
    110  
    111  
    112     def updateTree(self): 
    113         self.item0 = QTreeWidgetItem(self.treeRules, [""])        #the first row is different 
    114         self.buildLayer(self.item0, self.rulesLC, self.treeDepth)     # recursively builds as many layers as are in the................. 
    115  
    116  
    117     def buildLayer(self, parent, rulesLC, n): 
     115        self.buildLayer(None, self.rules, self.treeDepth) 
     116 
     117 
     118    def buildLayer(self, parent, rulesLC, n, startOfRule = ""): 
    118119        if n==0: 
    119             self.printRules(parent, rulesLC) 
     120            self.printRules(parent, rulesLC, startOfRule) 
    120121        elif n>0: 
    121             children = [] 
    122             for rule in rulesLC:                                 # for every rule 
    123                 for a in rule[0]:                                # for every antecedens 
    124                     if a not in children:                        # if it is not in the list of children, add it 
    125                         children.append(a) 
    126             for childText in children:                           # for every entry in the list of children 
    127                 item=QTreeWidgetItem(parent, [childText])             # add a branch with the text 
    128                 rules2=[] 
    129                 for rule in rulesLC:                             # find rules that go in this branch 
     122            children = set() 
     123            for rule in rulesLC: 
     124                children.update(rule[0]) 
     125            for childText in children: 
     126                item = QTreeWidgetItem(parent or self.treeRules, [childText]) 
     127                rules2 = [] 
     128                newStartOfRule = startOfRule + childText + "  "  
     129                for rule in rulesLC: 
    130130                    if childText in rule[0]: 
    131131                        if len(rule[0])==1: 
    132                             self.printRules(item, [[[],rule[1]]]) 
     132                            self.printRules(item, [(set(),) + rule[1:]], newStartOfRule) 
    133133                        else: 
    134                             rules2.append([rule[0][:],rule[1]]) # make a locla copy of rule 
    135                             rules2[-1][0].remove( childText)    # remove the element childText from the antecedenses 
    136                 self.buildLayer(item, rules2, n-1)              # recursively build next levels 
    137  
    138  
    139     def printRules(self, parent, rulesLC): 
    140         """ Prints whole rule or the rest of the rule, depending on WholeRules.isChecked(), as a child of parent.""" 
    141         startOfRule=""                                          # the part of rule that is already in the tree 
    142         gparent=parent 
    143         while str(gparent.text(0))!="": 
    144             startOfRule = str(gparent.text(0)) +"  "+startOfRule 
    145             gparent=gparent.parent() 
    146  
     134                            rules2.append((rule[0].difference([childText]),) + rule[1:]) 
     135                self.buildLayer(item, rules2, n-1, newStartOfRule) 
     136 
     137 
     138    def printRules(self, parent, rulesLC, startOfRule): 
    147139        for rule in rulesLC: 
    148             restOfRule=""                         # concatenate the part that is already in the tree 
    149             for s in rule[0]:                                   # with the rest of the antecedeses 
    150                 restOfRule=restOfRule+"  "+s 
    151  
    152             item = QTreeWidgetItem(parent, ["", str('%.3f' %rule[1][1]),str('%.3f' %rule[1][2]),str('%.3f' %rule[1][3]),str('%.3f' %rule[1][4]),str('%.3f' %rule[1][5]),str('%.3f' %rule[1][6])])             # add a branch with the text 
    153             self.wrlist.append([item, startOfRule + restOfRule+"  ->   "+rule[1][0] , restOfRule+"  ->   "+rule[1][0]]) 
    154  
    155  
    156     def removeSingleGrouping(self): 
    157         """Removes a row if it has a "+" and only one child.  """ 
    158         for line in self.wrlist:                    # go through the leaves of the tree 
    159             parent=line[0].parent() 
    160             if (parent.childCount())==1:            # if the parent has only one child 
    161                 line[2]=str(parent.text(0))+"  "+line[2]    # add the text to the leaf 
    162                 gparent = parent.parent()                   # find the grand-parent 
    163                 gparent.takeChild(gparent.indexOfChild(parent))  # remove the parent 
    164                 gparent.addChild(line[0])                 # insert a child 
    165  
     140            restOfRule = "  ".join(rule[0]) 
     141            remainder = restOfRule+"  ->   "+rule[1] 
     142            wholeRule = startOfRule + remainder 
     143            item = QTreeWidgetItem(parent,   [self.showWholeRules and wholeRule or remainder] 
     144                                           + [str('  %.3f  ' % v) for v in rule[2]]) 
     145            item.remainder = remainder 
     146            item.wholeRule = wholeRule 
     147            item.ruleId = rule[3] 
     148 
     149    def gatherRules(self, node, ids): 
     150        if hasattr(node, "ruleId"): 
     151            ids.add(node.ruleId) 
     152        for i in range(node.childCount()): 
     153            self.gatherRules(node.child(i), ids) 
     154 
     155    def purgeChanged(self): 
     156        if self.purgeAttributes: 
     157            if not self.purgeClassesCB.isEnabled(): 
     158                self.purgeClassesCB.setEnabled(True) 
     159                self.purgeClasses = self.oldPurgeClasses 
     160        else: 
     161            if self.purgeClassesCB.isEnabled(): 
     162                self.purgeClassesCB.setEnabled(False) 
     163                self.oldPurgeClasses = self.purgeClasses 
     164                self.purgeClasses = False 
     165     
     166    def selectionChanged(self): 
     167        ids = set() 
     168        for node in self.treeRules.selectedItems(): 
     169            self.gatherRules(node, ids) 
     170        self.selectedRules = orange.AssociationRules([self.origRules[id] for id in ids]) 
     171        leftids = set() 
     172        bothids = set() 
     173        for rule in self.selectedRules: 
     174            leftids.update(rule.matchLeft) 
     175            bothids.update(rule.matchBoth) 
     176        self.leftids = list(leftids) 
     177        self.bothids = list(bothids) 
     178        self.misids = list(leftids - bothids) 
     179        self.setInfo() 
     180        self.sendIf() 
     181 
     182    def sendIf(self): 
     183        if self.autoSend: 
     184            self.sendData() 
     185        else: 
     186            self.dataChanged = True 
     187             
     188    def sendData(self): 
     189        self.dataChanged = False 
     190        self.send("Association Rules", self.selectedRules) 
     191        if self.selectedRules: 
     192            examples = self.selectedRules[0].examples 
     193 
     194            coveredExamples = examples.getitemsref(self.leftids) 
     195            matchingExamples = examples.getitemsref(self.bothids) 
     196            mismatchingExamples = examples.getitemsref(self.misids) 
     197             
     198            if self.purgeAttributes or self.purgeClasses: 
     199                coveredExamples = OWTools.domainPurger(coveredExamples, self.purgeClasses) 
     200                matchingExamples = OWTools.domainPurger(matchingExamples, self.purgeClasses) 
     201                mismatchingExamples = OWTools.domainPurger(mismatchingExamples, self.purgeClasses) 
     202        else: 
     203            coveredExamples = matchingExamples = mismatchingExamples = None 
     204 
     205        self.send("Covered Examples", coveredExamples) 
     206        self.send("Matching Examples", matchingExamples) 
     207        self.send("Mismatching Examples", mismatchingExamples) 
     208         
     209 
     210    def setInfo(self): 
     211        if self.origRules: 
     212            self.nRules = len(self.rules) 
     213            if self.selectedRules: 
     214                self.nSelectedRules = len(self.selectedRules) 
     215                self.nSelectedExamples = len(self.leftids) 
     216                self.nMatchingExamples = len(self.bothids) 
     217                self.nMismatchingExamples = len(self.misids) 
     218            else: 
     219                self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = "" 
     220        else: 
     221            self.nRules = self.nSelectedRules = self.nSelectedExamples = self.nMatchingExamples = self.nMismatchingExamples = "" 
     222             
    166223 
    167224    def arules(self,arules): 
    168         self.rules = arules 
     225        self.origRules = arules 
     226        self.rules=[(set(str(val.variable.name) + (val.varType and "=" + str(val) or "") for val in rule.left if not val.isSpecial()), 
     227                     "  ".join(str(val.variable.name) + (val.varType and "=" + str(val) or "") for val in rule.right if not val.isSpecial()), 
     228                     (rule.support, rule.confidence, rule.lift, rule.leverage, rule.strength, rule.coverage), 
     229                     id 
     230                     ) 
     231                    for id, rule in enumerate(arules or [])] 
    169232        self.displayRules() 
     233        self.selectionChanged() 
    170234 
    171235if __name__=="__main__": 
  • orange/OrangeWidgets/Associate/OWAssociationRulesViewer.py

    r4989 r4995  
    11""" 
    2 <name>Association Rules Viewer</name> 
     2<name>Association Rules Filter</name> 
    33<description>Association rules filter and viewer.</description> 
    44<icon>icons/AssociationRulesViewer.png</icon> 
     
    317317                    if m[1] in ["Supp", "Conf", "Cov"]: 
    318318                        trules.normalizers.append((1, 1)) 
    319                     else: 
     319                    elif values: 
    320320                        mi, ma = min(values), max(values) 
    321321                        div = ma - mi 
    322322                        trules.normalizers.append((ma, div or 1)) 
     323                    else: 
     324                        trules.normalizers.append((0, 1)) 
    323325                    for row, meas in enumerate(values): 
    324326                        trules.setItem(row, col, QTableWidgetItem("  %.3f  " % meas)) 
Note: See TracChangeset for help on using the changeset viewer.