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

📄 owdatatable.py

📁 orange源码 数据挖掘技术
💻 PY
字号:
"""
<name>Data Table</name>
<description>Shows data in a spreadsheet.</description>
<icon>icons/DataTable.png</icon>
<priority>100</priority>
<contact>Peter Juvan (peter.juvan@fri.uni-lj.si)</contact>
"""

# OWDataTable.py
#
# wishes:
# ignore attributes, filter examples by attribute values, do
# all sorts of preprocessing (including discretization) on the table,
# output a new table and export it in variety of formats.

from qttable import *
from OWWidget import *
import OWGUI
import math

##############################################################################

class OWDataTable(OWWidget):
    settingsList = []

    def __init__(self, parent=None, signalManager = None):
        OWWidget.__init__(self, parent, signalManager, "Data Table")

        self.inputs = [("Examples", ExampleTable, self.dataset, Multiple)]
        self.outputs = []
        
        self.data = {}          # key: id, value: ExampleTable
        self.showMetas = {}     # key: id, value: (True/False, columnList)

        # info box
        #self.controlArea.layout().setResizeMode(QLayout.Minimum)
        infoBox = QVGroupBox("Info", self.controlArea)
        self.infoEx = QLabel('No data on input.', infoBox)
        self.infoMiss = QLabel('', infoBox)
        QLabel('', infoBox)
        self.infoAttr = QLabel('', infoBox)
        self.infoMeta = QLabel('', infoBox)
        QLabel('', infoBox)
        self.infoClass = QLabel('', infoBox)
        infoBox.setMinimumWidth(200)
        #infoBox.setMaximumHeight(infoBox.sizeHint().height())

        # settings box        
        boxSettings = QVGroupBox("Settings", self.controlArea)
        self.cbShowMeta = QCheckBox('Show meta attributes', boxSettings)
        self.cbShowMeta.setChecked(True)
        self.cbShowMeta.setEnabled(False)
        self.connect(self.cbShowMeta, SIGNAL("clicked()"), self.cbShowMetaClicked)
        self.btnResetSort = QPushButton("Restore Original Order", boxSettings)
        self.connect(self.btnResetSort, SIGNAL("clicked()"), self.btnResetSortClicked)
        boxSettings.setMaximumHeight(boxSettings.sizeHint().height())
        
        # GUI with tabs
        layout=QVBoxLayout(self.mainArea)
        self.tabs = QTabWidget(self.mainArea, 'tabWidget')
        self.id2table = {}  # key: widget id, value: table
        self.table2id = {}  # key: table, value: widget id
        layout.addWidget(self.tabs)
        self.connect(self.tabs,SIGNAL("currentChanged(QWidget*)"),self.tabClicked)
        

    def dataset(self, data, id=None):
        """Generates a new table and adds it to a new tab when new data arrives;
        or hides the table and removes a tab when data==None;
        or replaces the table when new data arrives together with already existing id.
        """
        if data:
            if self.data.has_key(id):
                # remove existing table
                self.data.pop(id)
                self.showMetas.pop(id)
                self.id2table[id].hide()
                self.tabs.removePage(self.id2table[id])
                self.table2id.pop(self.id2table.pop(id))
            self.data[id] = data
            self.showMetas[id] = (True, [])
            self.progressBarInit()
            table=QTable(None)
            table.setSelectionMode(QTable.NoSelection)
            self.id2table[id] = table
            self.table2id[table] = id
            tabName = data.name
            if not tabName:
                tabName = "(Unnamed)"
            tabName += " (" + str(id[1]) + ")"
            if id[2] != None:
                tabName += " [" + str(id[2]) + "]"
##            tabName = data.name + " "+str(id)
            self.tabs.insertTab(table, tabName)
            self.set_table(table, data)
            self.tabs.showPage(table)
            self.progressBarFinished()
            self.set_info(data)
            # enable showMetas checkbox only if metas exist
            self.cbShowMeta.setEnabled(len(self.showMetas[id][1])>0)
        elif self.data.has_key(id):
            self.data.pop(id)
            self.showMetas.pop(id)
            self.id2table[id].hide()
            self.tabs.removePage(self.id2table[id])
            self.table2id.pop(self.id2table.pop(id))
            self.set_info(self.data.get(self.table2id.get(self.tabs.currentPage(),None),None))
        # disable showMetas checkbox if there is no data on input
        if len(self.data) == 0:
            self.cbShowMeta.setEnabled(False)


    def tabClicked(self, qTableInstance):
        """Updates the info box and showMetas checkbox when a tab is clicked.
        """
        id = self.table2id.get(qTableInstance,None)
        self.set_info(self.data.get(id,None))
        show_col = self.showMetas.get(id,None)
        if show_col:
            self.cbShowMeta.setChecked(show_col[0])
            self.cbShowMeta.setEnabled(len(show_col[1])>0)

    def cbShowMetaClicked(self):
        table = self.tabs.currentPage()
        id = self.table2id.get(table, None)
        if self.showMetas.has_key(id):
            show,col = self.showMetas[id]
            self.showMetas[id] = (not(show),col)
        if show:
            for c in col:
                table.hideColumn(c)
        else:
            for c in col:
                table.showColumn(c)
                # we need to readjust the column width
                table.adjustColumn(c)
                table.setColumnWidth(c, table.columnWidth(c)+22)


    def btnResetSortClicked(self):
        """Sort the data by the last (hidden) column.
        """
        self.sortby = 0
        table = self.tabs.currentPage()
        if table:
            self.sort(table.numCols()-1)


    def set_info(self, data):
        """Updates data info.
        """
        def sp(l, capitalize=False):
            n = len(l)
            if n == 0:
                if capitalize:                    
                    return "No", "s"
                else:
                    return "no", "s"
            elif n == 1:
                return str(n), ''
            else:
                return str(n), 's'
        
        if not data:
            self.infoEx.setText('No data on input.')
            self.infoMiss.setText('')
            self.infoAttr.setText('')
            self.infoMeta.setText('')
            self.infoClass.setText('')
        else:
            self.infoEx.setText("%s example%s," % sp(data))
            missData = orange.Preprocessor_takeMissing(data)
            self.infoMiss.setText('%s (%.1f%s) with missing values.' % (len(missData), 100.*len(missData)/len(data), "%"))
            self.infoAttr.setText("%s attribute%s," % sp(data.domain.attributes,True))
            self.infoMeta.setText("%s meta attribute%s." % sp(data.domain.getmetas()))
            if data.domain.classVar:
                if data.domain.classVar.varType == orange.VarTypes.Discrete:
                    self.infoClass.setText('Discrete class with %s value%s.' % sp(data.domain.classVar.values))
                elif data.domain.classVar.varType == orange.VarTypes.Continuous:
                    self.infoClass.setText('Continuous class.')
                else:
                    self.infoClass.setText("Class neither discrete nor continuous.")
            else:
                self.infoClass.setText('Classless domain.')


    def set_table(self, table, data):
        """Writes data into table, adjusts the column width.
        """
        qApp.setOverrideCursor(QWidget.waitCursor)
        if data==None:
            return
        vars = data.domain.variables
        m = data.domain.getmetas() # getmetas returns a dictionary
        ml = [(k, m[k]) for k in m]
        ml.sort(lambda x,y: cmp(y[0], x[0]))
        metas = [x[1] for x in ml]
        metaKeys = [x[0] for x in ml]
        varsMetas = vars + metas
        numVars = len(data.domain.variables)
        numMetas = len(metas)
        numVarsMetas = numVars + numMetas
        numEx = len(data)
        numSpaces = int(math.log(numEx, 10))+1

        table.setNumCols(numVarsMetas+1)
        table.setNumRows(numEx)
        id = self.table2id.get(table,None)

        # set the header (attribute names)
        hheader=table.horizontalHeader()
        for i,var in enumerate(varsMetas):
            hheader.setLabel(i, var.name)
        hheader.setLabel(numVarsMetas, "")

        # set the contents of the table (values of attributes)
        # iterate variables
        for j,(key,attr) in enumerate(zip(range(numVars) + metaKeys, varsMetas)):
            self.progressBarSet(j*100.0/numVarsMetas)
            if attr == data.domain.classVar:
                bgColor = QColor(160,160,160)
            elif attr in metas:
                bgColor = QColor(220,220,200)
                self.showMetas[id][1].append(j) # store indices of meta attributes
            else:
                bgColor = Qt.white
            # generate list of tuples (attribute value, instance index) and sort by attrVal
            valIdx = [(ex[key].native(),idx) for idx,ex in enumerate(data)]
            valIdx.sort()
            # generate a dictionary where key: instance index, value: rank
            idx2rankDict = dict(zip([x[1] for x in valIdx], range(numEx)))
            for i in range(numEx):
                # set sorting key to ranks
                OWGUI.tableItem(table, i, j, str(data[i][key]), editType=QTableItem.Never, background=bgColor, sortingKey=self.sortingKey(idx2rankDict[i], numSpaces))
            # adjust the width of the table
            table.adjustColumn(j)
            table.setColumnWidth(j, table.columnWidth(j)+22)

        # add hidden column with consecutive numbers for restoring the original order of examples
        for i in range(numEx):
            OWGUI.tableItem(table, i, numVarsMetas, "", editType=QTableItem.Never, sortingKey=self.sortingKey(i, numSpaces))
        table.hideColumn(numVarsMetas)

        # adjust vertical header
        table.verticalHeader().setClickEnabled(False)
        table.verticalHeader().setResizeEnabled(False)
        table.verticalHeader().setMovingEnabled(False)
        
        # manage sorting (not correct, does not handle real values)
        self.connect(hheader,SIGNAL("clicked(int)"),self.sort)
        self.sortby = 0
        #table.setColumnMovingEnabled(1)
        qApp.restoreOverrideCursor()
        table.setCurrentCell(-1,-1)
        table.show()


    def sort(self, col):
        """Sorts the table by column col.
        """
        qApp.setOverrideCursor(QWidget.waitCursor)
        if col == self.sortby-1:
            self.sortby = - self.sortby
        else:
            self.sortby = col+1
        table = self.tabs.currentPage()
        table.sortColumn(col, self.sortby>=0, TRUE)
        table.horizontalHeader().setSortIndicator(col, self.sortby<0)
##        table.setSortIndicator(col, self.sortby>=0)
        qApp.restoreOverrideCursor()


    def sortingKey(self, val, len):
        """Returns a string with leading spaces followed by str(val), whose length is at least len.
        """
        s = "%0" + str(len) + "s"
        return s % str(val)


##############################################################################
# Test the widget, run from DOS prompt
# > python OWDataTable.py)
# Make sure that a sample data set (adult_sample.tab) is in the directory

if __name__=="__main__":
    a = QApplication(sys.argv)
    ow = OWDataTable()
    a.setMainWidget(ow)

##    d = orange.ExampleTable('wtclassed')
    d1 = orange.ExampleTable(r'..\..\doc\datasets\auto-mpg')
    d2 = orange.ExampleTable(r'..\..\doc\datasets\voting.tab')
    d3 = orange.ExampleTable(r'..\..\doc\datasets\sponge.tab')
    d4 = orange.ExampleTable(r'..\..\doc\datasets\wpbc.csv')
    d5 = orange.ExampleTable(r'..\..\doc\datasets\adult_sample.tab')
    ow.show()
    ow.dataset(d1,"auto-mpg")
    ow.dataset(d2,"voting")
##    ow.dataset(None,"auto-mpg")
##    ow.dataset(d3,"sponge")
##    ow.dataset(None,"voting")
##    ow.dataset(None,"sponge")
    ow.dataset(d4,"wpbc")
    ow.dataset(d5,"adult_sample")
    a.exec_loop()

⌨️ 快捷键说明

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