我正在阅读John Zelle撰写的Python编程,我被困在下图所示的练习中。
您可以在下面查看我的代码。我知道代码非常难看。 (感谢任何提示)
到目前为止,这是我的代码:
from graphics import *
def regression():
# creating the window for the regression line
win = GraphWin("Regression Line - Start Clicking!", 500, 500)
win.setCoords(0.0, 0.0, 10.0, 10.0)
rect = Rectangle(Point(0.5, 0.1), Point(2.5, 2.1))
rect.setFill("red")
rect.draw(win)
Text(rect.getCenter(), "Done").draw(win)
message = Text(Point(5, 0.5), "Click in this screen")
message.draw(win)
points = [] # list of points
n = 0 # count variable
sumX = 0
sumY = 0
while True:
p = win.getMouse()
p.draw(win)
# if user clicks in a red square it exits the loop and calculates the regression line
if (p.getX() >= 0.5 and p.getX() <= 2.5) and (p.getY() >= 0.1 and p.getY() <= 2.1):
break
n += 1 # count of the points
# get the sum of the X and Y points
sumX = sumX + p.getX()
sumY = sumY + p.getY()
# tuple of the X and Y points
dot = (p.getX(), p.getY())
points.append(dot)
avgX = sumX / n
avgY = sumY / n
top = 0
bottom = 0
# my ugly attempt at the regression equation shown in the book
for i in points:
gp = 0
numer = points[gp][0] * points[gp][1]
top = top + numer
denom = points[gp][0] ** 2
bottom = bottom + denom
gp += 1
m = (top - sumX * sumY) / (bottom - sumX ** 2)
y1 = avgY + m * (0.0 - avgX)
y2 = avgY + m * (10.0 - avgX)
regressionline = Line(Point(0, y1), Point(10.0, y2))
regressionline.draw(win)
raw_input("Press <Enter> to quit.")
win.close()
regression()
当我运行程序时,回归线似乎永远不是真正的最佳拟合线。我相信我在代码中错误地解释了回归方程。需要改变什么来获得正确的回归线?
答案 0 :(得分:4)
的问题:
from my_library import *
;更好地指定你想要的东西。这有助于保持名称空间整洁。
你有一大块代码;最好将其拆分为单独的功能。这使得思考和调试变得更加容易,并且可以帮助您稍后重用代码。当然,这是一个玩具问题,你不会重复使用它 - 但是做练习的全部意义在于养成良好的习惯,并且以这种方式分解代码绝对是一个好习惯!一般的经验法则 - 如果一个函数包含超过十几行代码,你应该考虑进一步分割它。
练习要求您在获取输入点时跟踪x,y,xx和xy运行总和。我认为这是一个坏主意 - 或者至少比Python更多的C-ish - 因为它迫使你一次完成两个不同的任务(获得积分并对它们进行数学运算)。我的建议是:如果你得分,得分;如果你在做数学,那就做数学;不要试图同时做两件事。
类似地,我不喜欢你的回归计算方式,担心窗户的两侧是什么。它为什么要知道或关心窗户?我希望你喜欢我的解决方案; - )
这是我的重构版代码:
from graphics import GraphWin, Point, Line, Rectangle, Text
def draw_window()
# create canvas
win = GraphWin("Regression Line - Start Clicking!", 500, 500)
win.setCoords(0., 0., 10., 10.)
# exit button
rect = Rectangle(Point(0.5, 0.1), Point(2.5, 2.1))
rect.setFill("red")
rect.draw(win)
Text(rect.getCenter(), "Done").draw(win)
# instructions
Text(Point(5., 0.5), "Click in this screen").draw(win)
return win
def get_points(win):
points = []
while True:
p = win.getMouse()
p.draw(win)
# clicked the exit button?
px, py = p.getX(), p.getY()
if 0.5 <= px <= 2.5 and 0.1 <= py <= 2.1:
break
else:
points.append((px,py))
return points
def do_regression(points):
num = len(points)
x_sum, y_sum, xx_sum, xy_sum = 0., 0., 0., 0.
for x,y in points:
x_sum += x
y_sum += y
xx_sum += x*x
xy_sum += x*y
x_mean, y_mean = x_sum/num, y_sum/num
m = (xy_sum - num*x_mean*y_mean) / (xx_sum - num*x_mean*x_mean)
def lineFn(xval):
return y_mean + m*(xval - x_mean)
return lineFn
def main():
# set up
win = draw_window()
points = get_points(win)
# show regression line
lineFn = do_regression(points)
Line(
Point(0., lineFn(0. )),
Point(10., lineFn(10.))
).draw(win)
# wait to close
Text(Point(5., 5.), "Click to exit").draw(win)
win.getMouse()
win.close()
if __name__=="__main__":
main()
答案 1 :(得分:3)
for
循环全部搞砸了!您有一个i
在循环中发生变化,但随后使用始终为0的gp
。
你想要更像的东西:
for (X, Y) in points:
numer += X * Y
denom += X * X
...或在for循环之前移动gp = 0
。
...或完全放弃该部分,并向sumXY
和sumXX
添加sumX
和sumY
。
无论哪种方式,一旦你修复它应该没问题(好吧,或者其他一些bug ......)。