📄 owsievediagram.py
字号:
######################################################################
## DATA signal
# receive new data and update all fields
def cdata(self, data):
self.interestingList.clear()
exData = self.data
#self.data = None
#if data: self.data = orange.Preprocessor_dropMissing(data)
if data: self.data = data
if not (self.data and exData and str(exData.domain.attributes) == str(self.data.domain.attributes)): # preserve attribute choice if the domain is the same
self.initCombos()
self.attributeSelection(self.attributeSelectionList)
######################################################################
## Attribute selection signal
def attributeSelection(self, attrList):
self.attributeSelectionList = attrList
if self.data and self.attributeSelectionList and len(attrList) >= 2:
try: # maybe not all attributes in attrList are in current data domain
self.attrX = attrList[0]
self.attrY = attrList[1]
except:
pass
self.updateData()
def clearGraph(self):
for item in self.canvas.allItems(): item.setCanvas(None) # remove all canvas items
for tip in self.tooltips: QToolTip.remove(self.canvasView, tip)
######################################################################
## UPDATEDATA - gets called every time the graph has to be updated
def updateData(self, *args):
self.clearGraph()
if not self.data: return
if not self.attrX or not self.attrY: return
data = self.getConditionalData()
valsX = []
valsY = []
contX = orange.ContingencyAttrAttr(self.attrX, self.attrX, data) # distribution of X attribute
contY = orange.ContingencyAttrAttr(self.attrY, self.attrY, data) # distribution of Y attribute
# compute contingency of x and y attributes
for key in contX.keys():
sum = 0
try:
for val in contX[key]: sum += val
except: pass
valsX.append(sum)
for key in contY.keys():
sum = 0
try:
for val in contY[key]: sum += val
except: pass
valsY.append(sum)
# create cartesian product of selected attributes and compute contingency
(cart, profit) = FeatureByCartesianProduct(data, [data.domain[self.attrX], data.domain[self.attrY]])
tempData = data.select(list(data.domain) + [cart])
contXY = orange.ContingencyAttrAttr(cart, cart, tempData) # distribution of X attribute
# compute probabilities
probs = {}
for i in range(len(valsX)):
valx = valsX[i]
for j in range(len(valsY)):
valy = valsY[j]
actualProb = 0
try:
for val in contXY['%s-%s' %(contX.keys()[i], contY.keys()[j])]: actualProb += val
except:
actualProb = 0
probs['%s-%s' %(contX.keys()[i], contY.keys()[j])] = ((contX.keys()[i], valx), (contY.keys()[j], valy), actualProb, len(data))
# get text width of Y attribute name
text = OWCanvasText(self.canvas, data.domain[self.attrY].name, x = 0, y = 0, bold = 1, show = 0)
xOff = text.boundingRect().right() - text.boundingRect().left() + 40
yOff = 50
sqareSize = min(self.canvasView.size().width() - xOff - 35, self.canvasView.size().height() - yOff - 30)
if sqareSize < 0: return # canvas is too small to draw rectangles
# print graph name
if self.attrCondition == "[None]":
name = "P(%s, %s) =\\= P(%s)*P(%s)" %(self.attrX, self.attrY, self.attrX, self.attrY)
else:
name = "P(%s, %s | %s = %s) =\\= P(%s | %s = %s)*P(%s | %s = %s)" %(self.attrX, self.attrY, self.attrCondition, getHtmlCompatibleString(self.attrConditionValue), self.attrX, self.attrCondition, getHtmlCompatibleString(self.attrConditionValue), self.attrY, self.attrCondition, getHtmlCompatibleString(self.attrConditionValue))
OWCanvasText(self.canvas, name , xOff+ sqareSize/2, 20, Qt.AlignCenter, bold = 1)
#OWCanvasText(self.canvas, "N = " + str(len(data)), xOff+ sqareSize/2, 30, Qt.AlignCenter, bold = 0)
######################
# compute chi-square
chisquare = 0.0
for i in range(len(valsX)):
for j in range(len(valsY)):
((xAttr, xVal), (yAttr, yVal), actual, sum) = probs['%s-%s' %(contX.keys()[i], contY.keys()[j])]
expected = float(xVal*yVal)/float(sum)
if expected == 0: continue
pearson2 = (actual - expected)*(actual - expected) / expected
chisquare += pearson2
######################
# draw rectangles
currX = xOff
for i in range(len(valsX)):
if valsX[i] == 0: continue
currY = yOff
width = int(float(sqareSize * valsX[i])/float(len(data)))
#for j in range(len(valsY)):
for j in range(len(valsY)-1, -1, -1): # this way we sort y values correctly
((xAttr, xVal), (yAttr, yVal), actual, sum) = probs['%s-%s' %(contX.keys()[i], contY.keys()[j])]
if valsY[j] == 0: continue
height = int(float(sqareSize * valsY[j])/float(len(data)))
# create rectangle
rect = OWCanvasRectangle(self.canvas, currX+2, currY+2, width-4, height-4, z = -10)
self.addRectIndependencePearson(rect, currX + 1, currY + 1, width-2, height-2, (xAttr, xVal), (yAttr, yVal), actual, sum)
self.addTooltip(currX+1, currY+1, width-2, height-2, (xAttr, xVal),(yAttr, yVal), actual, sum, chisquare)
currY += height
if currX == xOff:
OWCanvasText(self.canvas, data.domain[self.attrY].values[j], xOff - 10, currY - height/2, Qt.AlignRight+Qt.AlignVCenter, bold = 0)
OWCanvasText(self.canvas, data.domain[self.attrX].values[i], currX + width/2, yOff + sqareSize + 5, Qt.AlignCenter, bold = 0)
currX += width
# show attribute names
OWCanvasText(self.canvas, self.attrY, 5, yOff + sqareSize/2, Qt.AlignLeft, bold = 1)
OWCanvasText(self.canvas, self.attrX, xOff + sqareSize/2, yOff + sqareSize + 15, Qt.AlignCenter, bold = 1)
self.canvas.update()
######################################################################
## show deviations from attribute independence with standardized pearson residuals
def addRectIndependencePearson(self, rect, x, y, w, h, (xAttr, xVal), (yAttr, yVal), actual, sum):
expected = float(xVal*yVal)/float(sum)
pearson = (actual - expected) / sqrt(expected)
if pearson > 0: # if there are more examples that we would expect under the null hypothesis
intPearson = floor(pearson)
pen = QPen(QColor(0,0,255), 1); rect.setPen(pen)
b = 255
r = g = 255 - intPearson*20
r = g = max(r, 55) #
elif pearson < 0:
intPearson = ceil(pearson)
pen = QPen(QColor(255,0,0), 1)
rect.setPen(pen)
r = 255
b = g = 255 + intPearson*20
b = g = max(b, 55)
else:
pen = QPen(QColor(255,255,255), 1)
r = g = b = 255 # white
color = QColor(r,g,b)
brush = QBrush(color); rect.setBrush(brush)
if self.showCases and w > 6 and h > 6:
if self.showInColor:
if pearson > 0: c = QColor(0,0,255)
else: c = QColor(255, 0,0)
else: c = Qt.black
for i in range(int(actual)):
x1 = random.randint(x+1, x + w-4)
y1 = random.randint(y+1, y + h-4)
OWCanvasRectangle(self.canvas, x1, y1, 3, 3, penColor = c, brushColor = c, z = 100)
if pearson > 0:
pearson = min(pearson, 10)
kvoc = 1 - 0.08 * pearson # if pearson in [0..10] --> kvoc in [1..0.2]
else:
pearson = max(pearson, -10)
kvoc = 1 - 0.4*pearson
if self.showLines == 1: self.addLines(x,y,w,h, kvoc, pen)
#################################################
# add tooltips
def addTooltip(self, x,y,w,h, (xAttr, xVal), (yAttr, yVal), actual, sum, chisquare):
expected = float(xVal*yVal)/float(sum)
pearson = (actual - expected) / sqrt(expected)
tooltipText = """<b>X Attribute: %s</b><br>Value: <b>%s</b><br>Number of examples (p(x)): <b>%d (%.2f%%)</b><br><hr>
<b>Y Attribute: %s</b><br>Value: <b>%s</b><br>Number of examples (p(y)): <b>%d (%.2f%%)</b><br><hr>
<b>Number Of Examples (Probabilities):</b><br>Expected (p(x)p(y)): <b>%.1f (%.2f%%)</b><br>Actual (p(x,y)): <b>%d (%.2f%%)</b><br>
<hr><b>Statistics:</b><br>Chi-square: <b>%.2f</b><br>Standardized Pearson residual: <b>%.2f</b>""" %(self.attrX, getHtmlCompatibleString(xAttr), xVal, 100.0*float(xVal)/float(sum), self.attrY, getHtmlCompatibleString(yAttr), yVal, 100.0*float(yVal)/float(sum), expected, 100.0*float(xVal*yVal)/float(sum*sum), actual, 100.0*float(actual)/float(sum), chisquare, pearson )
tipRect = QRect(x, y, w, h)
QToolTip.add(self.canvasView, tipRect, tooltipText)
self.tooltips.append(tipRect)
##################################################
# add lines
def addLines(self, x,y,w,h, diff, pen):
if self.showLines == 0: return
if diff == 0: return
#if (xVal == 0) or (yVal == 0) or (actualProb == 0): return
# create lines
dist = 20 # original distance between two lines in pixels
dist = dist * diff
temp = dist
while (temp < w):
OWCanvasLine(self.canvas, temp+x, y+1, temp+x, y+h-2, 1, pen.color())
temp += dist
temp = dist
while (temp < h):
OWCanvasLine(self.canvas, x+1, y+temp, x+w-2, y+temp, 1, pen.color())
temp += dist
##################################################
## SAVING GRAPHS
##################################################
def saveToFileCanvas(self):
sizeDlg = OWChooseImageSizeDlg(self.canvas)
sizeDlg.exec_loop()
#test widget appearance
if __name__=="__main__":
a=QApplication(sys.argv)
ow=OWSieveDiagram()
a.setMainWidget(ow)
ow.show()
ow.cdata(orange.ExampleTable(r"c:\Development\Python23\Lib\site-packages\Orange\datasets\crush injury - cont.tab"))
a.exec_loop()
ow.saveSettings()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -