📄 owsievediagram.py
字号:
"""
<name>Sieve Diagram</name>
<description>Sieve diagram.</description>
<contact>Gregor Leban (gregor.leban@fri.uni-lj.si)</contact>
<icon>icons/SieveDiagram.png</icon>
<priority>4200</priority>
"""
# OWSieveDiagram.py
#
from OWWidget import *
from qt import *
from qtcanvas import *
import orngInteract, OWGUI
from OWQCanvasFuncts import *
from math import sqrt, floor, ceil, pow
from orngCI import FeatureByCartesianProduct
import random
from OWTools import getHtmlCompatibleString
from OWDlgs import OWChooseImageSizeDlg
###########################################################################################
##### WIDGET :
###########################################################################################
class OWSieveDiagram(OWWidget):
settingsList = ["showLines", "showCases", "showInColor"]
def __init__(self,parent=None, signalManager = None):
OWWidget.__init__(self, parent, signalManager, "Sieve diagram", TRUE)
self.controlArea.setMinimumWidth(250)
self.inputs = [("Examples", ExampleTable, self.cdata, Default), ("Attribute selection", list, self.attributeSelection)]
self.outputs = []
#set default settings
self.data = None
self.attrX = ""
self.attrY = ""
self.attrCondition = None
self.attrConditionValue = None
self.showLines = 1
self.showCases = 0
self.showInColor = 1
self.attributeSelectionList = None
self.stopCalculating = 0
self.tooltips = []
#load settings
self.loadSettings()
self.box = QVBoxLayout(self.mainArea)
self.canvas = QCanvas(2000, 2000)
self.canvasView = QCanvasView(self.canvas, self.mainArea)
self.box.addWidget(self.canvasView)
self.canvasView.show()
self.canvas.resize(self.canvasView.size().width()-5, self.canvasView.size().height()-5)
#GUI
self.attrSelGroup = OWGUI.widgetBox(self.controlArea, box = " Shown Attributes ")
self.attrXCombo = OWGUI.comboBoxWithCaption(self.attrSelGroup, self, "attrX", "X Attribute:", tooltip = "Select an attribute to be shown on the X axis", callback = self.updateData, sendSelectedValue = 1, valueType = str, labelWidth = 70)
self.attrYCombo = OWGUI.comboBoxWithCaption(self.attrSelGroup, self, "attrY", "Y Attribute:", tooltip = "Select an attribute to be shown on the Y axis", callback = self.updateData, sendSelectedValue = 1, valueType = str, labelWidth = 70)
self.conditionGroup = OWGUI.widgetBox(self.controlArea, box = " Condition ")
self.attrConditionCombo = OWGUI.comboBoxWithCaption(self.conditionGroup, self, "attrCondition", "Attribute:", callback = self.updateConditionAttr, sendSelectedValue = 1, valueType = str, labelWidth = 70)
self.attrConditionValueCombo = OWGUI.comboBoxWithCaption(self.conditionGroup, self, "attrConditionValue", "Value:", callback = self.updateData, sendSelectedValue = 1, valueType = str, labelWidth = 70)
box2 = OWGUI.widgetBox(self.controlArea, box = " Visual Settings ")
OWGUI.checkBox(box2, self, "showLines", "Show Lines", callback = self.updateData)
hbox = OWGUI.widgetBox(box2, orientation = "horizontal")
OWGUI.checkBox(hbox, self, "showCases", "Show Data Examples...", callback = self.updateData)
OWGUI.checkBox(hbox, self, "showInColor", "...In Color", callback = self.updateData)
self.interestingGroupBox = OWGUI.widgetBox(self.controlArea, box = " Interesting Attribute Pairs ")
self.calculateButton = OWGUI.button(self.interestingGroupBox, self, "Calculate Chi Squares", callback = self.calculatePairs)
self.stopCalculateButton = OWGUI.button(self.interestingGroupBox, self, "Stop Evaluation", callback = self.stopCalculateClick)
self.stopCalculateButton.hide()
self.interestingList = QListBox(self.interestingGroupBox)
self.connect(self.interestingList, SIGNAL("selectionChanged()"),self.showSelectedPair)
self.connect(self.graphButton, SIGNAL("clicked()"), self.saveToFileCanvas)
self.icons = self.createAttributeIconDict()
self.resize(800, 550)
random.seed()
###############################################################
# when clicked on a list box item, show selected attribute pair
def showSelectedPair(self):
if self.interestingList.count() == 0: return
index = self.interestingList.currentItem()
(chisquare, strName, self.attrX, self.attrY) = self.chisquares[index]
self.updateData()
def calculatePairs(self):
self.chisquares = []
self.interestingList.clear()
self.stopCalculating = 0
if not self.data: return
self.calculateButton.hide()
self.stopCalculateButton.show()
discAttrs = []
for attr in self.data.domain:
if self.data.domain[attr].varType == orange.VarTypes.Discrete: discAttrs.append(attr)
discData = self.data.select(discAttrs)
self.progressBarInit()
total = len(discData.domain)* len(discData.domain) / 2.0
current = 0
#for attrX in range(len(data.domain)):
for attr1 in range(len(discData.domain)):
attrX = discData.domain[attr1].name
#for attrY in range(attrX+1, len(data.domain)):
for attr2 in range(attr1+1, len(discData.domain)):
attrY = discData.domain[attr2].name
current += 1
if self.stopCalculating:
self.progressBarFinished()
self.calculateButton.show()
self.stopCalculateButton.hide()
return
data = self.getConditionalData(attrX, attrY)
if len(data) == 0: continue
dcX = orange.ContingencyAttrAttr(attrX, attrX, data) # distribution of X attribute
valsX = [sum(dcX[key]) for key in dcX.keys()] # compute contingency of x attribute
dcY = orange.ContingencyAttrAttr(attrY, attrY, data) # distribution of X attribute
valsY = [sum(dcY[key]) for key in dcY.keys()] # compute contingency of x attribute
# create cartesian product of selected attributes and compute contingency
(cart, profit) = FeatureByCartesianProduct(data, [data.domain[attrX], data.domain[attrY]])
tempData = data.select(list(data.domain) + [cart])
contXY = orange.ContingencyAttrAttr(cart, cart, tempData) # distribution of the merged attribute
# compute chi-square
chisquare = 0.0
for i in range(len(valsX)):
valx = valsX[i]
for j in range(len(valsY)):
valy = valsY[j]
actual = 0
try:
for val in contXY['%s-%s' %(dcX.keys()[i], dcY.keys()[j])]: actual += val
except:
actual = 0
expected = float(valx * valy) / float(len(data))
if expected == 0: continue
pearson2 = (actual - expected)*(actual - expected) / expected
chisquare += pearson2
i = 0
while i < len(self.chisquares) and self.chisquares[i][0] > chisquare: i += 1
self.chisquares.insert(i, (chisquare, "%s - %s" % (attrX, attrY), attrX, attrY))
self.interestingList.insertItem("%s - %s (%.3f)" % (attrX, attrY, chisquare), i)
self.progressBarSet(100.0*current/float(total))
qApp.processEvents()
self.progressBarFinished()
self.calculateButton.show()
self.stopCalculateButton.hide()
def stopCalculateClick(self):
self.stopCalculating = 1
######################################
# create data subset depending on conditional attribute and value
def getConditionalData(self, xAttr = None, yAttr = None, dropMissingData = 1):
if not self.data: return None
if not xAttr: xAttr = self.attrX
if not yAttr: yAttr = self.attrY
if self.attrCondition == "[None]":
data = self.data.select([xAttr, yAttr])
else:
data = orange.Preprocessor_dropMissing(self.data.select([xAttr, yAttr, self.attrCondition]))
data = data.select({self.attrCondition:self.attrConditionValue})
if dropMissingData: return orange.Preprocessor_dropMissing(data)
else: return data
######################################
# new conditional attribute was set - update graph
def updateConditionAttr(self):
self.attrConditionValueCombo.clear()
if self.attrCondition == "[None]":
self.updateData()
return
for val in self.data.domain[self.attrCondition].values:
self.attrConditionValueCombo.insertItem(val)
self.attrConditionValue = str(self.attrConditionValueCombo.text(0))
self.updateData()
##################################################
# initialize lists for shown and hidden attributes
def initCombos(self):
self.attrXCombo.clear()
self.attrYCombo.clear()
self.attrConditionCombo.clear()
self.attrConditionCombo.insertItem("[None]")
self.attrConditionValueCombo.clear()
if not self.data: return
for i in range(len(self.data.domain)):
if self.data.domain[i].varType == orange.VarTypes.Continuous: continue
self.attrXCombo.insertItem(self.icons[self.data.domain[i].varType], self.data.domain[i].name)
self.attrYCombo.insertItem(self.icons[self.data.domain[i].varType], self.data.domain[i].name)
self.attrConditionCombo.insertItem(self.icons[self.data.domain[i].varType], self.data.domain[i].name)
self.attrCondition = str(self.attrConditionCombo.text(0))
if self.attrXCombo.count() > 0:
self.attrX = str(self.attrXCombo.text(0))
self.attrY = str(self.attrYCombo.text(self.attrYCombo.count() > 1))
def resizeEvent(self, e):
OWWidget.resizeEvent(self,e)
self.canvas.resize(self.canvasView.size().width()-5, self.canvasView.size().height()-5)
self.updateData()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -