📄 owinteractivediscretization.py
字号:
"""
<name>Interactive Discretization</name>
<description>Interactive discretization of continuous attributes</description>
<icon>icons/InteractiveDiscretization.png</icon>
<priority>2105</priority>
<contact>Ales Erjavec (ales.erjavec(@at@)fri.uni-lj.si)</contact>
"""
import orange
from OWWidget import *
from OWGraph import *
from qt import *
from qtcanvas import *
import OWGUI, OWGraphTools
import Numeric
def frange(low, up, steps):
inc=(up-low)/steps
return [low+i*inc for i in range(steps)]
class DiscGraph(OWGraph):
def __init__(self, master, *args):
OWGraph.__init__(self, *args)
self.master=master
self.rugKeys = []
self.cutLineKeys = []
self.cutMarkerKeys = []
self.probCurveKey = None
self.baseCurveKey = None
self.lookaheadCurveKey = None
self.customLink = -1
self.setAxisScale(QwtPlot.yRight, 0.0, 1.0, 0.0)
self.setYLaxisTitle("Split gain")
self.setXaxisTitle("Attribute value")
self.setYRaxisTitle("Class probability")
self.setShowYRaxisTitle(1)
self.setShowYLaxisTitle(1)
self.setShowXaxisTitle(1)
self.enableYRightAxis(1)
self.resolution=50
self.setCursor(Qt.arrowCursor)
self.canvas().setCursor(Qt.arrowCursor)
self.data = self.attr = self.contingency = None
self.minVal = self.maxVal = 0
self.curCutPoints=[]
def computeAddedScore(self, spoints):
candidateSplits = [x for x in frange(self.minVal, self.maxVal, self.resolution) if x not in spoints]
idisc = orange.IntervalDiscretizer(points = [-99999] + spoints)
var = idisc.constructVariable(self.data.domain[self.master.continuousIndices[self.master.selectedAttr]])
measure = self.master.measures[self.master.measure][1]
score=[]
chisq = self.master.measure == 2
for cut in candidateSplits:
idisc.points = spoints + [cut]
idisc.points.sort()
score.append(measure(var, self.data))
return candidateSplits, score
def computeBaseScore(self):
if self.data:
self.baseCurveX, self.baseCurveY = self.computeAddedScore(list(self.curCutPoints))
def computeLookaheadScore(self, split):
if self.data:
self.lookaheadCurveX, self.lookaheadCurveY = self.computeAddedScore(list(self.curCutPoints) + [split])
def setData(self, attr, data):
self.clear()
self.attr, self.data = attr, data
self.curCutPoints = []
if not data:
return
self.classColors = OWGraphTools.ColorPaletteHSV(len(data.domain.classVar.values))
if not attr:
return
self.contingency = orange.ContingencyAttrClass(attr, data)
self.condProb = orange.ConditionalProbabilityEstimatorConstructor_loess(self.contingency)
attrValues = self.contingency.keys()
self.minVal, self.maxVal = min(attrValues), max(attrValues)
self.snapDecimals = -int(math.ceil(math.log(self.maxVal-self.minVal, 10)) -2)
self.replotAll()
def plotRug(self, noUpdate = False):
for rug in self.rugKeys:
self.removeCurve(rug)
self.rugKeys = []
if self.data and self.master.showRug:
targetClass = self.master.targetClass
freqhigh = [(val, freq[targetClass]) for val, freq in self.contingency.items() if freq[targetClass] > 1e-6]
freqlow = [(val, freq.abs - freq[targetClass]) for val, freq in self.contingency.items()]
freqlow = [f for f in freqlow if f[1] > 1e-6]
if not freqhigh or not freqlow:
return
freqfac = .1 / max(max([f[1] for f in freqhigh]), max([f[1] for f in freqlow]))
for val, freq in freqhigh:
c = self.addCurve("", Qt.gray, Qt.gray, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = [val, val], yData = [1.0, 1.0 - max(.02, freqfac * freq)])
self.setCurveYAxis(c, QwtPlot.yRight)
self.rugKeys.append(c)
for val, freq in freqlow:
c = self.addCurve("", Qt.gray, Qt.gray, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = [val, val], yData = [0.04, 0.04 + max(.02, freqfac * freq)])
self.setCurveYAxis(c, QwtPlot.yRight)
self.rugKeys.append(c)
if not noUpdate:
self.update()
def plotBaseCurve(self, noUpdate = False):
if self.baseCurveKey:
self.removeCurve(self.baseCurveKey)
if self.data and self.master.showBaseLine:
self.setAxisOptions(QwtPlot.yLeft, self.master.measure == 3 and QwtAutoScale.Inverted or QwtAutoScale.None)
self.baseCurveKey = self.addCurve("", Qt.black, Qt.black, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = self.baseCurveX, yData = self.baseCurveY, lineWidth = 2)
self.setCurveYAxis(self.baseCurveKey, QwtPlot.yLeft)
else:
self.baseCurveKey = None
if not noUpdate:
self.update()
def plotLookaheadCurve(self, noUpdate = False):
if self.lookaheadCurveKey:
self.removeCurve(self.lookaheadCurveKey)
if self.data and self.master.showLookaheadLine:
self.setAxisOptions(QwtPlot.yLeft, self.master.measure == 3 and QwtAutoScale.Inverted or QwtAutoScale.None)
self.lookaheadCurveKey = self.addCurve("", Qt.black, Qt.black, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = self.lookaheadCurveX, yData = self.lookaheadCurveY, lineWidth = 1)
self.setCurveYAxis(self.lookaheadCurveKey, QwtPlot.yLeft)
self.curve(self.lookaheadCurveKey).setEnabled(1)
else:
self.lookaheadCurveKey = None
if not noUpdate:
self.update()
def plotProbCurve(self, noUpdate = False):
if self.probCurveKey:
self.removeCurve(self.probCurveKey)
if self.data and self.master.showTargetClassProb:
xData = self.contingency.keys()[1:-1]
self.probCurveKey = self.addCurve("", Qt.gray, Qt.gray, 1, style = QwtCurve.Lines, symbol = QwtSymbol.None, xData = xData, yData = [self.condProb(x)[self.master.targetClass] for x in xData], lineWidth = 2)
self.setCurveYAxis(self.probCurveKey, QwtPlot.yRight)
else:
self.probCurveKey = None
if not noUpdate:
self.update()
def plotCutLines(self):
attr = self.data.domain[self.master.continuousIndices[self.master.selectedAttr]]
for c in self.cutLineKeys:
self.removeCurve(c)
for m in self.cutMarkerKeys:
self.removeMarker(m)
self.cutLineKeys = []
self.cutMarkerKeys = []
for cut in self.curCutPoints:
c = self.addCurve("", Qt.blue, Qt.blue, 1, style = QwtCurve.Steps, symbol = QwtSymbol.None, xData = [cut, cut], yData = [.9, 0.1])
self.setCurveYAxis(c, QwtPlot.yRight)
self.cutLineKeys.append(c)
m = self.addMarker(str(attr(cut)), cut, .9, Qt.AlignCenter + Qt.AlignTop, bold=1)
self.setMarkerYAxis(m, QwtPlot.yRight)
self.cutMarkerKeys.append(m)
def getCutCurve(self, cut):
ccc = self.transform(QwtPlot.xBottom, cut)
for i,c in enumerate(self.curCutPoints):
cc = self.transform(QwtPlot.xBottom, c)
if abs(cc-ccc)<3:
curve = self.curve(self.cutLineKeys[i])
curve.curveInd = i
return curve
return None
def setSplits(self, splits):
if self.data:
self.curCutPoints = splits
self.computeBaseScore()
self.plotBaseCurve()
self.plotCutLines()
self.customLink = -1
def addCutPoint(self, cut):
self.curCutPoints.append(cut)
c = self.addCurve("", Qt.blue, Qt.blue, 1, style = QwtCurve.Steps, symbol = QwtSymbol.None, xData = [cut, cut], yData = [1.0, 0.015])
self.setCurveYAxis(c, QwtPlot.yRight)
self.cutLineKeys.append(c)
curve = self.curve(c)
curve.curveInd = len(self.cutLineKeys) - 1
return curve
def onMousePressed(self, e):
if not self.data:
return
self.mouseCurrentlyPressed = 1
cut = self.invTransform(QwtPlot.xBottom, e.x())
curve = self.getCutCurve(cut)
if not curve and self.master.snap:
curve = self.getCutCurve(round(cut, self.snapDecimals))
if curve:
if e.button() == Qt.RightButton:
self.curCutPoints.pop(curve.curveInd)
self.plotCutLines()
else:
cut = self.curCutPoints.pop(curve.curveInd)
self.plotCutLines()
self.selectedCutPoint=self.addCutPoint(cut)
else:
self.selectedCutPoint=self.addCutPoint(cut)
self.plotCutLines()
self.update()
self.computeBaseScore()
self.plotBaseCurve()
self.master.synchronizeIf()
def onMouseMoved(self, e):
if not self.data:
return
if self.mouseCurrentlyPressed:
if self.selectedCutPoint:
pos = self.invTransform(QwtPlot.xBottom, e.x())
if self.master.snap:
pos = round(pos, self.snapDecimals)
if self.curCutPoints[self.selectedCutPoint.curveInd]==pos:
return
if pos > self.maxVal or pos < self.minVal:
self.curCutPoints.pop(self.selectedCutPoint.curveInd)
self.computeBaseScore()
self.plotCutLines()
self.mouseCurrentlyPressed = 0
return
self.curCutPoints[self.selectedCutPoint.curveInd] = pos
self.selectedCutPoint.setData([pos, pos], [.9, 0.1])
self.computeLookaheadScore(pos)
self.plotLookaheadCurve()
self.update()
self.master.synchronizeIf()
elif self.getCutCurve(self.invTransform(QwtPlot.xBottom, e.x())):
self.canvas().setCursor(Qt.sizeHorCursor)
else:
self.canvas().setCursor(Qt.arrowCursor)
def onMouseReleased(self, e):
if not self.data:
return
self.mouseCurrentlyPressed = 0
self.selectedCutPoint = None
self.computeBaseScore()
self.plotBaseCurve()
self.plotCutLines()
self.master.synchronizeIf()
if self.lookaheadCurveKey:
self.curve(self.lookaheadCurveKey).setEnabled(0)
self.update()
def targetClassChanged(self):
self.plotRug()
self.plotProbCurve()
def replotAll(self):
self.clear()
if not self.contingency:
return
self.computeBaseScore()
self.plotRug(True)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -