source: orange/Orange/OrangeWidgets/Data/OWPurgeDomain.py @ 11380:973b73da21b1

Revision 11380:973b73da21b1, 8.3 KB checked in by Ales Erjavec <ales.erjavec@…>, 14 months ago (diff)

Added new icons for Purge Domain and PLS Regression widgets.

Line 
1"""
2<name>Purge Domain</name>
3<description>Removes redundant values and attributes, sorts values.</description>
4<icon>icons/PurgeDomain.svg</icon>
5<contact>Janez Demsar (janez.demsar(@at@)fri.uni-lj.si)</contact>
6<priority>1105</priority>
7"""
8from OWWidget import *
9import OWGUI
10
11import orange
12
13class OWPurgeDomain(OWWidget):
14
15    def __init__(self, parent=None, signalManager=None):
16        OWWidget.__init__(self, parent, signalManager, 'PurgeDomain', wantMainArea=False)
17        self.settingsList=["removeValues", "removeAttributes", "removeClassAttribute", "removeClasses", "autoSend", "sortValues", "sortClasses"]
18
19        self.inputs = [("Data", ExampleTable, self.setData)]
20        self.outputs = [("Data", ExampleTable)]
21
22        self.data = None
23
24        self.preRemoveValues = self.removeValues = 1
25        self.removeAttributes = 1
26        self.removeClassAttribute = 1
27        self.preRemoveClasses = self.removeClasses = 1
28        self.autoSend = 1
29        self.dataChanged = False
30
31        self.sortValues = self.sortClasses = True
32
33        self.loadSettings()
34
35        self.removedAttrs = self.reducedAttrs = self.resortedAttrs = self.classAttr = "-"
36
37        boxAt = OWGUI.widgetBox(self.controlArea, "Attributes", addSpace=True)
38        OWGUI.checkBox(boxAt, self, 'sortValues', 'Sort attribute values', callback = self.optionsChanged)
39        rua = OWGUI.checkBox(boxAt, self, "removeAttributes", "Remove attributes with less than two values", callback = self.removeAttributesChanged)
40
41        ruv = OWGUI.checkBox(OWGUI.indentedBox(boxAt, sep=OWGUI.checkButtonOffsetHint(rua)), self, "removeValues", "Remove unused attribute values", callback = self.optionsChanged)
42        rua.disables = [ruv]
43        rua.makeConsistent()
44
45
46        boxAt = OWGUI.widgetBox(self.controlArea, "Classes", addSpace=True)
47        OWGUI.checkBox(boxAt, self, 'sortClasses', 'Sort classes', callback = self.optionsChanged)
48        rua = OWGUI.checkBox(boxAt, self, "removeClassAttribute", "Remove class attribute if there are less than two classes", callback = self.removeClassesChanged)
49        ruv = OWGUI.checkBox(OWGUI.indentedBox(boxAt, sep=OWGUI.checkButtonOffsetHint(rua)), self, "removeClasses", "Remove unused class values", callback = self.optionsChanged)
50        rua.disables = [ruv]
51        rua.makeConsistent()
52
53
54        box3 = OWGUI.widgetBox(self.controlArea, 'Statistics', addSpace=True)
55        OWGUI.label(box3, self, "Removed attributes: %(removedAttrs)s")
56        OWGUI.label(box3, self, "Reduced attributes: %(reducedAttrs)s")
57        OWGUI.label(box3, self, "Resorted attributes: %(resortedAttrs)s")
58        OWGUI.label(box3, self, "Class attribute: %(classAttr)s")
59       
60        box2 = OWGUI.widgetBox(self.controlArea, "Send")
61        btSend = OWGUI.button(box2, self, "Send data", callback = self.process, default=True)
62        cbAutoSend = OWGUI.checkBox(box2, self, "autoSend", "Send automatically")
63
64        OWGUI.setStopper(self, btSend, cbAutoSend, "dataChanged", self.process)
65       
66        OWGUI.rubber(self.controlArea)
67
68#        OWGUI.separator(self.controlArea, height=24)
69
70        #self.adjustSize()
71
72    def setData(self, dataset):
73        if dataset:
74            self.data = dataset
75            self.process()
76        else:
77            self.reducedAttrs = self.removedAttrs = self.resortedAttrs = self.classAttr = ""
78            self.send("Data", None)
79            self.data = None
80        self.dataChanged = False
81
82    def removeAttributesChanged(self):
83        if not self.removeAttributes:
84            self.preRemoveValues = self.removeValues
85            self.removeValues = False
86        else:
87            self.removeValues = self.preRemoveValues
88        self.optionsChanged()
89
90    def removeClassesChanged(self):
91        if not self.removeClassAttribute:
92            self.preRemoveClasses = self.removeClasses
93            self.removeClasses = False
94        else:
95            self.removeClasses = self.preRemoveClasses
96        self.optionsChanged()
97
98    def optionsChanged(self):
99        if self.autoSend:
100            self.process()
101        else:
102            self.dataChanged = True
103
104    def sortAttrValues(self, attr, interattr=None):
105        if not interattr:
106            interattr = attr
107
108        newvalues = list(interattr.values)
109        newvalues.sort()
110        if newvalues == list(interattr.values):
111            return interattr
112
113        newattr = orange.EnumVariable(interattr.name, values=newvalues)
114        newattr.getValueFrom = orange.ClassifierByLookupTable(newattr, attr)
115        lookupTable = newattr.getValueFrom.lookupTable
116        distributions = newattr.getValueFrom.distributions
117        for val in interattr.values:
118            idx = attr.values.index(val)
119            lookupTable[idx] = val
120            distributions[idx][newvalues.index(val)] += 1
121        return newattr
122
123    def process(self):
124        if self.data == None:
125            return
126
127        self.reducedAttrs = 0
128        self.removedAttrs = 0
129        self.resortedAttrs = 0
130        self.classAttribute = 0
131
132        if self.removeAttributes or self.sortValues:
133            newattrs = []
134            for attr in self.data.domain.attributes:
135                if attr.varType == orange.VarTypes.Continuous:
136                    if orange.RemoveRedundantOneValue.has_at_least_two_values(self.data, attr):
137                        newattrs.append(attr)
138                    else:
139                        self.removedAttrs += 1
140                    continue
141
142                if attr.varType != orange.VarTypes.Discrete:
143                    newattrs.append(attr)
144                    continue
145
146                if self.removeValues:
147                    newattr = orange.RemoveUnusedValues(attr, self.data)
148                    if not newattr:
149                        self.removedAttrs += 1
150                        continue
151
152                    if newattr != attr:
153                        self.reducedAttrs += 1
154                else:
155                    newattr = attr
156
157                if self.removeValues and len(newattr.values) < 2:
158                    self.removedAttrs += 1
159                    continue
160
161                if self.sortValues:
162                    newnewattr = self.sortAttrValues(attr, newattr)
163                    if newnewattr != newattr:
164                        self.resortedAttrs += 1
165                        newattr = newnewattr
166
167                newattrs.append(newattr)
168        else:
169            newattrs = self.data.domain.attributes
170
171
172        klass = self.data.domain.classVar
173        classChanged = False
174        if not klass:
175            newclass = klass
176            self.classAttr = "No class"
177        elif klass.varType != orange.VarTypes.Discrete:
178            newclass = klass
179            self.classAttr = "Class is not discrete"
180        elif not (self.removeClassAttribute or self.sortClasses):
181            newclass = klass
182            self.classAttr = "Class is not checked"
183        else:
184            self.classAttr = ""
185
186            if self.removeClasses:
187                newclass = orange.RemoveUnusedValues(klass, self.data)
188            else:
189                newclass = klass
190
191            if not newclass or self.removeClassAttribute and len(newclass.values) < 2:
192                newclass = None
193                self.classAttr = "Class is removed"
194            elif len(newclass.values) != len(klass.values):
195                    self.classAttr = "Class is reduced"
196
197            if newclass and self.sortClasses:
198                newnewclass = self.sortAttrValues(klass, newclass)
199                if newnewclass != newclass:
200                    if self.classAttr:
201                        self.classAttr = "Class is reduced and sorted"
202                    else:
203                        self.classAttr = "Class is sorted"
204                    newclass = newnewclass
205
206            if not self.classAttr:
207                self.classAttr = "Class is unchanged"
208
209        if self.reducedAttrs or self.removedAttrs or self.resortedAttrs or newclass != klass:
210            newDomain = orange.Domain(newattrs, newclass)
211            newData = orange.ExampleTable(newDomain, self.data)
212        else:
213            newData = self.data
214
215        self.send("Data", newData)
216
217        self.dataChanged = False
218
219
220if __name__=="__main__":
221    appl = QApplication(sys.argv)
222    ow = OWPurgeDomain()
223    #data = orange.ExampleTable('..\\..\\doc\\datasets\\car.tab')
224    #data.domain.attributes[3].values.append("X")
225    #ow.setData(data)
226    ow.show()
227    appl.exec_()
228    ow.saveSettings()
Note: See TracBrowser for help on using the repository browser.