⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 owfeatureselection.py

📁 orange源码 数据挖掘技术
💻 PY
📖 第 1 页 / 共 3 页
字号:
"""
<name>Feature Selection</name>
<description>Removes features from the data according to some criteria.</description>
<icon>icons/SelectData.png</icon>
<priority>3500</priority>
"""

import orange
from OWWidget import *
from qttable import *
import OWGUI
from orngTextCorpus import *

class OWFeatureSelection(OWWidget):

    settingsList = ["updateOnChange", "loadedConditions", "loadedVarNames"]

    def __init__(self, parent = None, signalManager = None, name = "Select data"):
        OWWidget.__init__(self, parent, signalManager, name)  #initialize base class

        # set channels
        self.inputs = [("Examples", ExampleTable, self.onDataInput)]
        self.outputs = [("Examples", ExampleTable)]
        
        # manually set member variables
        self.name2var = {}   # key: variable name, item: orange.Variable
        self.Conditions = []

        # handled member variables
        self.currentVar = None
        self.NegateCondition = False
        self.currentOperatorDict = {orange.VarTypes.Continuous:Operator(Operator.operatorsC[0], orange.VarTypes.Continuous),
                                    orange.VarTypes.Discrete:Operator(Operator.operatorsD[0],orange.VarTypes.Discrete),
                                    orange.VarTypes.String:Operator(Operator.operatorsS[0], orange.VarTypes.String)}
        self.Num1 = 0.0
        self.Num2 = 0.0
        self.Str1 = ""
        self.Str2 = ""
        self.currentVals = []
        self.CaseSensitive = False
        self.updateOnChange = True

        # load settings
        self.loadedVarNames = []
        self.loadedConditions = []
        self.loadSettings()
        
        # GUI
        self.mainArea.setFixedWidth(0)
        ca=QFrame(self.controlArea)
        ca.adjustSize()
        gl=QGridLayout(ca,4,3,5)

        # attribute condition box
        boxAttrCond = QVGroupBox('Attribute Condition', ca)
        gl.addMultiCellWidget(boxAttrCond, 0,0,0,2)
        frmAttrCond = QFrame(boxAttrCond)
        frmAttrCond.adjustSize()
        glac=QGridLayout(frmAttrCond,1,3,5)
        glac.setColStretch(0,2)
        glac.setColStretch(1,1)
        glac.setColStretch(2,2)

        # attributes
        boxAttr = QVGroupBox(frmAttrCond)
        glac.addWidget(boxAttr,0,0)
        boxAttr.setTitle('Attribute')
        self.lbAttr = QListBox(boxAttr, 'SelAttr')
        self.connect(self.lbAttr, SIGNAL('selectionChanged()'), self.lbAttrChange)

        # operators
        boxOper = QVGroupBox('Operator', frmAttrCond)
        # operators 0: empty
        self.lbOperatosNone = QListBox(boxOper, 'SelAttr')
        # operators 1: discrete
        self.lbOperatorsD = QListBox(boxOper, 'SelAttr')
        self.lbOperatorsD.hide()
        self.connect(self.lbOperatorsD, SIGNAL('selectionChanged()'), self.lbOperatorsChange)
        for op in Operator.operatorsD + [Operator.operatorDef]:
            self.lbOperatorsD.insertItem(op)
        # operators 2: continuous
        self.lbOperatorsC = QListBox(boxOper, 'SelAttr')
        self.lbOperatorsC.hide()
        self.connect(self.lbOperatorsC, SIGNAL('selectionChanged()'), self.lbOperatorsChange)
        for op in Operator.operatorsC + [Operator.operatorDef]:
            self.lbOperatorsC.insertItem(op)
        # operators 6: string
        self.lbOperatorsS = QListBox(boxOper, 'SelAttr')
        self.lbOperatorsS.hide()
        self.connect(self.lbOperatorsS, SIGNAL('selectionChanged()'), self.lbOperatorsChange)
        for op in Operator.operatorsS + [Operator.operatorDef]:
            self.lbOperatorsS.insertItem(op)
        self.lbOperatorsDict = {0: self.lbOperatosNone,
                                orange.VarTypes.Continuous: self.lbOperatorsC,
                                orange.VarTypes.Discrete: self.lbOperatorsD,
                                orange.VarTypes.String: self.lbOperatorsS}
        # NOT checkbox
        glac.addWidget(boxOper,0,1)
        self.cbNot = OWGUI.checkBox(boxOper, self, "NegateCondition", "NOT")

        # values
        self.valuesStack = QWidgetStack(frmAttrCond)
        glac.addWidget(self.valuesStack,0,2)
        # values 0: empty
        boxVal = QVGroupBox("Values", None)
        self.valuesStack.addWidget(boxVal, 0)
        # values 2: continuous between num and num
        boxVal = QVGroupBox("Values", None)
        self.valuesStack.addWidget(boxVal, orange.VarTypes.Continuous)
        self.leNum1 = OWGUI.lineEdit(boxVal, self, "Num1")
        self.lblAndCon = OWGUI.widgetLabel(boxVal, "and")
        self.leNum2 = OWGUI.lineEdit(boxVal, self, "Num2")
        boxAttrStat = QVGroupBox("Statistics", boxVal)
        self.lblMin = QLabel("Min: ", boxAttrStat)
        self.lblAvg = QLabel("Avg: ", boxAttrStat)
        self.lblMax = QLabel("Max: ", boxAttrStat)
        # values 1: discrete
        boxVal = QVGroupBox("Values", None)
        self.valuesStack.addWidget(boxVal, orange.VarTypes.Discrete)
        self.lbVals = QListBox(boxVal)
        self.connect(self.lbVals , SIGNAL('selectionChanged()'), self.lbValsChange)
        # values 6: string between str and str
        boxVal = QVGroupBox("Values", None)
        self.valuesStack.addWidget(boxVal, orange.VarTypes.String)
        self.leStr1 = OWGUI.lineEdit(boxVal, self, "Str1")
        self.lblAndStr = OWGUI.widgetLabel(boxVal, "and")
        self.leStr2 = OWGUI.lineEdit(boxVal, self, "Str2")
        self.cbCaseSensitive = OWGUI.checkBox(boxVal, self, "CaseSensitive", "Case sensitive")

        # buttons Add, Update, Remove, Disjunction, Up, Down
        self.boxButtons = QHBox(ca)
        gl.addMultiCellWidget(self.boxButtons, 1,1,0,2)
        btnNew = OWGUI.button(self.boxButtons, self, "Add", self.OnNewCondition)
        self.btnUpdate = OWGUI.button(self.boxButtons, self, "Update", self.OnUpdateCondition)
        self.btnRemove = OWGUI.button(self.boxButtons, self, "Remove", self.OnRemoveCondition)        
        self.btnOR = OWGUI.button(self.boxButtons, self, "OR", self.OnDisjunction)        
        self.btnMoveUp = OWGUI.button(self.boxButtons, self, "Move Up", self.btnMoveUpClicked)        
        self.btnMoveDown = OWGUI.button(self.boxButtons, self, "Move Down", self.btnMoveDownClicked)
        self.btnRemove.setEnabled(False)
        self.btnUpdate.setEnabled(False)
        self.btnMoveUp.setEnabled(False)
        self.btnMoveDown.setEnabled(False)

        # data selection criteria
        boxCriteria = QVGroupBox(ca)
        boxCriteria.setTitle('Data Selection Criteria')
        gl.addMultiCellWidget(boxCriteria, 2,2,0,2)
        self.criteriaTable = QTable(boxCriteria)
        self.criteriaTable.setShowGrid(False)
        self.criteriaTable.setSelectionMode(QTable.NoSelection)
        self.criteriaTable.setNumCols(2)
        self.criteriaTable.verticalHeader().setClickEnabled(False)
        self.criteriaTable.verticalHeader().setResizeEnabled(False,-1)
        hheader=self.criteriaTable.horizontalHeader()
        hheader.setClickEnabled(False)
        hheader.setLabel(0, "Active      ")
        hheader.setLabel(1, "Condition")
        self.connect(self.criteriaTable, SIGNAL('currentChanged(int, int)'), self.currentCriteriaChange)
        self.criteriaTable.adjustColumn(0)
        self.criteriaTable.setColumnWidth(1, 360)

        # data in
        boxDataIn = QVGroupBox(ca)
        boxDataIn.setTitle('Data In')
        gl.addWidget(boxDataIn, 3,0)
        self.dataInExamplesLabel = OWGUI.widgetLabel(boxDataIn, "num examples")
        self.dataInAttributesLabel = OWGUI.widgetLabel(boxDataIn, "num attributes")

        # data out
        boxDataOut = QVGroupBox(ca)
        boxDataOut.setTitle('Data Out')
        gl.addWidget(boxDataOut, 3,1)        
        self.dataOutExamplesLabel = OWGUI.widgetLabel(boxDataOut, "num examples")
        self.dataOutAttributesLabel = OWGUI.widgetLabel(boxDataOut, "num attributes")

        # update
        boxSettings = QVGroupBox(ca)
        boxSettings.setTitle('Update')
        gl.addWidget(boxSettings, 3,2)
        OWGUI.checkBox(boxSettings, self, "updateOnChange", "Update on any change", box=None)
        btnUpdate = OWGUI.button(boxSettings, self, "Update", self.setOutput)

        # icons
        self.icons = self.createAttributeIconDict()
        self.onDataInput(None)
        self.lbOperatorsD.setCurrentItem(0)
        self.lbOperatorsC.setCurrentItem(0)
        self.lbOperatorsS.setCurrentItem(0)
        self.resize(500,661)
        
        self.measures = FeatureSelection.measures.keys() 


    ############################################################################################################################################################
    ## Data input and output management ########################################################################################################################
    ############################################################################################################################################################

    def onDataInput(self, data):
        """Loads stored conditions (if we have a similar domain), updates list boxes and data in info, sends out data.
        """
        self.fs = FeatureSelection(data)
        self.bas = orange.DomainBasicAttrStat(self.fs.data)
        if self.fs.data:
            # set self.name2var
            varList = self.fs.data.domain.variables.native() + self.fs.data.domain.getmetas().values()
            varNames = []
            for v in varList:
                self.name2var[v.name] = v
                varNames.append(v.name)
            if varNames == self.loadedVarNames:
                if self.Conditions == []:
                    self.Conditions = self.loadedConditions
            else:
                self.loadedVarNames = varNames
            if self.lbAttr.count() <> len(varList):
                # update attribute listbox
                self.lbAttr.clear()
                for v in varList:
                    self.lbAttr.insertItem(self.icons[v.varType], v.name)
                self.lbAttr.setSelected(0,True)
                # clear conditions and criteria table
                self.Conditions = []
                for row in range(self.criteriaTable.numRows()-1,-1,-1):
                    self.criteriaTable.clearCellWidget(row,0)
                    self.criteriaTable.clearCell(row,1)
                    self.criteriaTable.hideRow(row)
                self.criteriaTable.setNumRows(0)
            self.criteriaTable.setCurrentCell(-1,1)
            self.boxButtons.setEnabled(True)
        else:
            self.name2var = {}
            self.Conditions = []
            self.lbAttr.clear()
            self.currentVar = None
            for row in range(self.criteriaTable.numRows()-1,-1,-1):
                self.criteriaTable.clearCellWidget(row,0)
                self.criteriaTable.clearCell(row,1)
                self.criteriaTable.hideRow(row)
            self.criteriaTable.setNumRows(0)
            self.criteriaTable.setCurrentCell(-1,1)
            self.boxButtons.setEnabled(False)
        # update operators, values and info, and send out data
        self.updateOperatorStack()
        self.updateValuesStack()
        self.updateInfoIn(data)
        self.setOutput()
        

    def setOutput(self):
        """Sends out data, updates data out info.
        """
        if self.fs.data:            
            filterList = self.getFilterList(self.fs.data.domain, self.Conditions, enabledOnly=True)
            if len(filterList)>0:
                filter = orange.Filter_disjunction([orange.Filter_conjunction(l) for l in filterList])
            else:
                filter = orange.Filter_conjunction([]) # a filter that does nothing
                
            matchingOutput = self.fs.selectFeatures(filter)
        else:
            matchingOutput = None

        self.send("Examples", matchingOutput)

        self.updateInfoOut(matchingOutput)


    def getFilterList(self, domain, conditions, enabledOnly):
        """Returns list of lists of orange filters, e.g. [[f1,f2],[f3]].
        OR is always enabled (with no respect to cond.enabled)
        """
        fdList = [[]]
        for cond in conditions:
            if cond.type == "OR":
                fdList.append([])
            elif cond.enabled or not enabledOnly:
                fdList[-1].append(cond.operator.getFilter(domain, cond.varName, cond.val1, cond.val2, cond.negated, cond.caseSensitive))
##        # remove the first list if empty
##        if len(fdList) > 1 and len(fdList[0]) == 0:
##            fdList.pop(0)
        return fdList


    ############################################################################################################################################################
    ## Callback handlers ###################################################################################################################################
    ############################################################################################################################################################

    def lbAttrChange(self):
        """Updates operator listBox and value stack, only if necesarry.
        """
        text = str(self.lbAttr.currentText())
        prevVar = self.currentVar
        if prevVar:
            prevVarType = prevVar.varType
            prevVarName = prevVar.name

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -