第 11 章 绘图以及类的进一步扩展
11 PLOTTING AND MORE ABOUT CLASSES
曲政 / 2018-04-29
图形的有很大意义吗?为什么很多程序都用语言输出?
一张图可以表达很多意思。中国有这个谚语,一图胜千言?
非不想也,实不便也。
在 Python 生态里,很幸运,可以方便画图。
11.1 Plotting using Pylab
pylab 的官方资源?
PyLab 绘图能力的完整用户指南参见 https://matplotlib.org/users/index.html
完整的颜色和线型标识符列表,参见 http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot
rcParams 中有很多设置项目,完整的列表参见 http://matplotlib.org/users/customizing.html
如果你不想花费精力对这些参数进行单独设置,可以使用一个预定义的样式表,具体介绍参见 http://matplotlib.org/users/style_sheets.html#style-sheets
pylab.show () 怎么用好?
放在代码的最末尾。因为它会导致程序挂起,直到关闭窗口。这有时候很麻烦。
生成图片不 show 出来?并不傻,可以保存啊。
pylab.figure (2) #创建图 2
pylab.plot ([1,4,2,3], [5,6,7,8]) #在图 2 上绘图
pylab.savefig ('Figure-Addie') #保存图 2
pylab 默认保存为什么格式?
扩展名会是.png,表示文件的格式是可移植网络图形(Portable Network Graphics)这是一种表示图形的公共领域标准。
画图出来要做到什么礼貌?
图都有标题,坐标轴都有标注。不能让看的人自己猜。
排版 typography 中 “点 point” 是什么概念?
1 点是 1/72 英寸,0.3527mm
绘图颜色很重要吗?
很重要,不能忽视。
too important to ignore
11.2 Plotting Mortgages, an Extended Example
pylab 与 matplotlab 官方网站上的例子好像不大合。
但是可以运行。
array 比 list 更方便?
更多线性代数工具。
比如
a1 = pylab.array ([1, 2, 4])
print ('a1 =', a1)
a2 = a1*2
print ('a2 =', a2)
print ('a1 + 3 =', a1 + 3)
print ('3 - a1 =', 3 - a1)
print ('a1 - a2 =', a1 - a2)
print ('a1*a2 =', a1*a2)
输出
a1 = [1 2 4]
a2 = [2 4 8]
a1 + 3 = [4 5 7]
3 - a1 = [2 1 -1]
a1 - a2 = [-1 -2 -4]
a1*a2 = [2 8 32]
pylab 对 list 做了什么处理?
把 list 转成 array,nam = pylab.array (lis) 只不过是明说了一次。
每月还款额 怎么画,什么样?
#每个月的还款额,等额还款,基本是水平线
def plotPayments (self, style):
pylab.plot (self.paid [1:], style, label = self.legend) #第一个月是 0,不必画出来,y 轴不从 0 开始。
待还本金 怎么画,什么样?
#每个月看一眼待还本金,总是在减少,但是速度不同哦
def plotBalance (self, style):
pylab.plot (self.outstanding, style, label = self.legend)
已付总额 怎么画,什么样?
#截止到每个月的已经付给银行的总额
def plotTotPd (self, style):
totPd = [self.paid [0]] #用 0 月金额初始化
for i in range (1, len (self.paid)):
totPd.append (totPd [-1] + self.paid [i]) #上月结算额 + 本月新增额 = 本月结算额
pylab.plot (totPd, style, label = self.legend)
初始五年放大看
净成本 怎么画,什么样?
#本金当然要还,除去还本金,付的利息总额是净成本
def plotNet (self, style):
#算一遍每月累积总额 totPd
totPd = [self.paid [0]]
for i in range (1, len (self.paid)):
totPd.append (totPd [-1] + self.paid [i])
#用 outstanding 待还本金数组的长度初始化 equityAcquired
equityAcquired = pylab.array ([self.loan] * \
len (self.outstanding))
#初始本金 - 待还本金 = 已还本金总额
equityAcquired = equityAcquired - \
pylab.array (self.outstanding)
#总净成本 = 已付总额 - 已还本金总额
net = pylab.array (totPd) - equityAcquired
pylab.plot (net, style, label = self.legend)
放大一点看消长变化
如何批量绘图,分别标注?
用 for 循环分别激活各张图,分别画入三条线。
用 labelPlot 函数分别给四张图做标注。
#建一个给图做标注的函数,顺便存档
def labelPlot (figure, title, xLabel, yLabel):
pylab.figure (figure)
pylab.title (title)
pylab.xlabel (xLabel)
pylab.ylabel (yLabel)
pylab.legend (loc = 'best')
pylab.savefig (title)
styles = ['b-', 'g-.', 'r:']
#给图编号赋名,方便理解和区分
payments, cost, balance, netCost = 0, 1, 2, 3
for i in range (len (morts)):
pylab.figure (payments)
morts [i].plotPayments (styles [i])
pylab.figure (cost)
morts [i].plotTotPd (styles [i])
pylab.figure (balance)
morts [i].plotBalance (styles [i])
pylab.figure (netCost)
morts [i].plotNet (styles [i])
labelPlot (payments, 'Monthly Payments of $' + str (amt) +
' Mortgages', 'Months', 'Monthly Payments')
labelPlot (cost, 'Cash Outlay of $' + str (amt) +
'Mortgages', 'Months', 'Total Payments')
labelPlot (balance, 'Balance Remaining of $' + str (amt) +
'Mortgages', 'Months', 'Remaining Loan Balance of $')
labelPlot (netCost, 'Net Cost of $' + str (amt) + ' Mortgages',
'Months', 'Payments - Equity $')
以上,2018-04-24。