在前面介绍了这么多内容以后,我们这节来介绍一个实际的项目,利用Python中一些实用的模块和方法来根据数据来画一张图表,图表的内容可以很直观的反映出你所获得的数据。图表的内容可以很多,也可以很少。这完全是由你自己来定的。具体来说的话就是利用图形创建一个PDF文件,将从文本中读取的数据可视化。
初步来说,你所设计的程序要能实现以下的功能:
实现这些功能光依靠简单的程序是不行的,我们还需要一些好用的工具包。在这里我们需要的是ReportLab工具包,它很容易使用并且为PDF中的图形和文档生成提供了丰富的功能。
在初步的实现中,程序这是把数据以一系列元组的形式放入源代码。这样的方法很容易就可以得到实现。看看下面这个例子:
data=[
# Year Month Predicted High Low
(2007, 12, 4.8, 5.0, 4.7),
(2008, 1, 4.3, 4.4, 4.2),
#You can add more information here
]
根据所需要的数据你可以在后续的部位添加更多的数据,并将其以元组的形式存入到data这个列表里面。数据的类别主要有:年份、月份、预测值、最高值、最低值。
接着我们会将数据的获取方式作出一些修改,前面讲过的网络编程中我们可以直接从网络上获取数据。使用标准模块urllib,这个模块和open函数很类似,但它是用一个URL而不是文件名作为参数。在打开并阅读文件时,你需要过滤掉不需要的内容。文件包含空行以及一些特殊的字符,程序中我们都应该将这些东西处理掉。
data=[]
for line in urlopen(URL).readlines():
if not line.isspace() and not line[0] in COMMENT_CHARS:
data.append([float(n) for n in line.split()])
其中变量 COMMENT_CHARS被设定为字符串‘#:’
ReportLab由很多部分组成并且允许用户使用多种方法输出。生成PDF是最基本的模块是pdfgen。它包含一个Canvas类,这个类有很多画图的方法。
这个项目里面使用的是较为高级的图形框架,具体来说在report.graphics包以及它的子模块中,利用它可以直接画出各种形式的对象,然后将这些对象添加到Drawing对象中,以便稍后将该对象输出到PDF格式的文件中。来看下面这样一段代码:
from reportlab.graphics.shapes import Drawing,String
from reportlab.graphics import renderPDF
d=Drawing(100,100)
s=String(25,50,'Hello,World!', TextAnchor='middle')
d.add(s)
renderPDF.drawToFile(d,'hello.pdf','A simple PDf file')
首先我们生成一个给定带下的图纸,也就是Drawing。像素大小为100*100。然后创建带有一些属性的元素,在这里是一个String对象,接着将元素添加到图纸中去,最后将图纸生成为PDF格式并且保存到文件中。对于renderPDF.drawToFile方法会把你的PDF文件存到当前目录的一个名为hello.pdf的文件中。
Sring构造函数的参数主要是x,y的坐标以及要显示的文本。我们还可以提供其他特性:字号、颜色等等。可以看见在这个例子中我们提供的是TextAnchor,说明字符串应该被放在给定坐标处。运行结果如下:
会在当前的工程中生成一个hello.pdf文件,当你双击打卡这个PDF文件的时候,会显示如右边所示的内容,和上面程序中的设计是如出一辙的。我们实现了基本的图形绘制和文档生成。
为了再进一步直观的观察数据,我们加入一些彼此连接在一起的折线。对于折线,ReportLab有特定的类:PolyLine。
PolyLine把一个坐标列表作为第一个参数,列表的形式是[(x0,y0),(x1,y1).......],对于每个(x,y)坐标对应生成折线上一个点。曲线图的创建需要对应数据集合中的每一列,折线上每个点都由年、月、值组成。具体的操作可以通过下面的代码来实现:
pred=[row[2] for row in data]
drawing.add(PolyLine(zip(times,pred),stockeColor=color.blue))
LinePlot类的作用在于它的实例化不需要任何参数,然后在将他添加到Drawing前设置它的几个特性。要设置的主要是:x,y,height,width,data等。前面四个是不需要说明的,后面一个是点的坐标列表,它是元组的列表就像在PolyLines中的那样。
from urllib import urlopen
from reportlab.graphics.shapes import *
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics.charts.textlabels import Label
from reportlab.graphics import renderPDF
URL='http://www.swpc.noaa.gov/ftpdir/week/Predict.txt'#这个URL可能链接不到或者域名以及转移,只是作为例子而展示。
COMMENT_CHARS='#:'
drawing=Drawing(400,200)
data=[]
for line in urlopen(URL).readlines():
if not line.isspace() and not line[0] in COMMENT_CHARS:
data.append([float(n) for n in line.split()])
pred=[row[2] for row in data]
high=[row[3] for row in data]
low=[row[4] for row in data]
times=[row[0]+row[1]/12.0 for row in data]
lp=LinePlot()
lp.x=50
lp.y=50
lp.height=125
lp.width=300
lp.data=[zip(times,pred),zip(times,high),zip(times,low)]
lp.lines[0].strokeColor=colors.blue
lp.lines[1].strokerColor=colors.red
lp.lines[2].stokerColor=colors.green
drawing.add(lp)
drawing.add(String(250,150,'Sunspots',fontSize=14,fillColor=colors.red))
renderPDF.drawToFile(drawing,'report.pdf','Sunspots')
上述的的程序将前面的初步实现中的一些内容整合起来,相信大家很容易就能看懂。可以尝试换掉URL来试试这个框架的作用,动手实践得到你想要的结果。这个项目就介绍到这里,下一章节预告--未知。