帮助解决约翰·泽尔的Python编程练习(8-13)

1 投票
1 回答
3152 浏览
提问于 2025-04-16 19:03

这个程序看起来能正常工作,但生成的线性回归线似乎并不是最合适的那条线。

我觉得问题可能出在公式的实现上。我不太确定我是否理解正确,也不确定我在练习的最后一段中是否做了应该做的事情。

这是图形库的链接:http://mcsp.wartburg.edu/zelle/python/ppics1/code/graphics.py,如果你想试试的话。

这是练习的内容:

写一个程序,能够在图形界面上绘制回归线,也就是通过一组点绘制的最佳拟合线。首先,让用户通过在图形窗口中点击来指定数据点。为了结束输入,可以在窗口的左下角放一个标记为“完成”的小矩形;当用户点击这个矩形时,程序就会停止收集点。回归线的公式如下:

这是公式:https://i.stack.imgur.com/xj2uu.jpg,我不能发图片。

x是所有x值的平均数,y是所有y值的平均数。当用户点击点时,程序应该在图形窗口中绘制这些点,并记录输入值的数量以及x、y、x²和xy值的总和。当用户点击“完成”矩形时,程序会使用上面的公式计算窗口左右边缘的x值对应的y值,从而计算出回归线的起点和终点。在画出这条线后,程序会暂停,等待用户再次点击,然后再关闭窗口并退出。

我似乎无法正确格式化代码,所以我附上了这个链接:http://pastebin.com/JsQ0eM2R

# 8-13-LOB.py

from graphics import *

def listMulti(list1,list2):
    tempAcc = 0
    for i in range(len(list1)):
        tempAcc += list1[i] * list2[i]
    print tempAcc
    return tempAcc

def squareList(iterable):
    itSum = 0
    for i in iterable:
        itSum += i**2
    return itSum

def listMean(iterable):
    return sum(iterable)/len(iterable)

def regression(xList,yList,win):
    xBar = listMean(xList)
    yBar = listMean(yList)
    xListSq = squareList(xList)
    xListXyList = listMulti(xList,yList)

    m = ((xListXyList) - ((len(xList)*xBar*yBar)))/\
        ((xListSq) - (len(xList)* (xBar**2)))

    y1 = yBar + m*(-50.0 - xBar)
    y2 = yBar + m*(50.0 - xBar)

    Line(Point(-50.0,y1),Point(50.0,y2)).draw(win)

    return "ybar: %f\txBar: %f\tm: %f\ty1: %f\ty2: %f" %(yBar,xBar,m,y1,y2)

def windraw():
    win = GraphWin("Line of Best Fit",500,500)
    win.setCoords(-50.0,-50.0,50.0,50.0)

    doneBox = Rectangle(Point(-50,-50),Point(-40,-45))
    doneBox.setWidth(3)

    doneBoxTxt = Text(Point(-45,-47.5),"DONE")

    doneBox.draw(win)
    doneBoxTxt.draw(win)

    return win

def pointBuild(xList,yList,win):
    tempPoint = Point(25,25) # prime tempPoint for sentinel loop
    # tests if given point is past rectangle created for doneBox
    while (tempPoint.getX() - (Point(-40,-45)).getX() == abs(tempPoint.getX() - (Point(-40,-45)).getX())) or\
          (tempPoint.getY() - (Point(-40,-45)).getY() == abs(tempPoint.getY() - (Point(-40,-45)).getY())):

        tempPoint = win.getMouse()
        tempPoint.draw(win)
        xList.append(tempPoint.getX()); yList.append(tempPoint.getY())


def main():
    xList,yList = [],[]

    win = windraw()
    pointBuild(xList,yList,win)
    print regression(xList,yList,win)


    # Test out coordinate lists accumulation from pointBuild
    for i in range(len(xList)-1):
        print "Point(%2.2f,%2.2f)" % (xList[i],yList[i])

    win.getMouse()
    win.close()


main()

1 个回答

1

我觉得问题出在你的pointBuild这个函数上,它把用户在“完成”框里点击的点加到了回归列表里,所以每个数据集在左下角都有一个点。你可以通过在pointBuild返回之前加上“print xList, yList”来确认这一点。我建议你把这个函数改成:

while True: # (a common python idiom for "do forever until we break")
    tempPoint = win.getMouse()
    if (tempPoint is in the DONE rectangle):
        # get out, we're done: don't forget to handle the case where
        # there are no points in xList/yList!
        break
    else:
        # draw the point
        # add it to xList, yList

我还觉得你可能需要看看“是否在完成矩形内”的逻辑。如果我理解正确的话,你只是想知道tempPoint.getX()的值是否在-50和-40之间,以及.getY()的值是否在-50和-45之间。

祝你好运!

撰写回答