Python进阶第五课(简单项目)--画张图

1.前言

    在前面介绍了这么多内容以后,我们这节来介绍一个实际的项目,利用Python中一些实用的模块和方法来根据数据来画一张图表,图表的内容可以很直观的反映出你所获得的数据。图表的内容可以很多,也可以很少。这完全是由你自己来定的。具体来说的话就是利用图形创建一个PDF文件,将从文本中读取的数据可视化。

2.初步实现

    初步来说,你所设计的程序要能实现以下的功能:

  • 从Internet上下载所需要的数据文件。
  • 分析数据文件并提取感兴趣的地方。
  • 根据文件生成PDF文件。

 实现这些功能光依靠简单的程序是不行的,我们还需要一些好用的工具包。在这里我们需要的是ReportLab工具包,它很容易使用并且为PDF中的图形和文档生成提供了丰富的功能。

2.1获取数据

    在初步的实现中,程序这是把数据以一系列元组的形式放入源代码。这样的方法很容易就可以得到实现。看看下面这个例子:

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被设定为字符串‘#:’

2.2使用ReportLab画图

2.2.1基础图形

        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,说明字符串应该被放在给定坐标处。运行结果如下:

Python进阶第五课(简单项目)--画张图_第1张图片Python进阶第五课(简单项目)--画张图_第2张图片

    会在当前的工程中生成一个hello.pdf文件,当你双击打卡这个PDF文件的时候,会显示如右边所示的内容,和上面程序中的设计是如出一辙的。我们实现了基本的图形绘制和文档生成。

2.2.2加入折线

    为了再进一步直观的观察数据,我们加入一些彼此连接在一起的折线。对于折线,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))

2.2.3使用LinePlot类

    LinePlot类的作用在于它的实例化不需要任何参数,然后在将他添加到Drawing前设置它的几个特性。要设置的主要是:x,y,height,width,data等。前面四个是不需要说明的,后面一个是点的坐标列表,它是元组的列表就像在PolyLines中的那样。

3.最终实现 

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来试试这个框架的作用,动手实践得到你想要的结果。这个项目就介绍到这里,下一章节预告--未知。

你可能感兴趣的:(Python)