绘制图表(1):初次实现

今天介绍如何用Python创建图表。具体地说,你将创建一个PDF文件,其中包含的图表对从文本文件读取的数据进行了可视化。虽然常规的电子表格软件都提供这样的功能,但Python提供了更强大的功能。当你再次实现这个项目并从网上自动下载数据时,就意识到这一点。

之前介绍了HTML和XML,今天,你将遇到另一个很熟悉的缩略语——PDF。它指的是可移植的文档格式(portable document format)。PDF是Adobe开发的一种格式,可表示任何包含图形和文本的文档。不同于Microsoft Word等文档,PDF文件是不可编辑的,但有适用于大多数平台的免费阅读器软件。另外,无论在哪种平台使用什么阅读器来查看,显示的PDF文件都相同;而HTML格式则不是这样的,它要求平台安装指定的字体,还必须将图片作为独立的文件进行传输。

1.1.问题描述

Python很善于分析数据。相比于使用普通的电子表格软件,使用Python提供的文件和字符串处理功能来根据数据文件创建某些报表可能更容易,在执行复杂的编程逻辑时尤其如此。

使用字符串格式设置功能可打印出漂亮的输出,如分列打印数字。然而,在有些情况下,仅使用纯文本还不够。(俗话说,一图胜千言。)在今天,你将学习ReportLab包的基本知识,它能够让你像创建纯文本一样轻松地创建PDF格式(和其他格式)的图形和文档。

学习今天将介绍的概念时,建议你去找些有趣的应用程序。今天将根据有关太阳黑子的数据(来自美国国家海洋和大气管理局的空间天气预测中心)创建一个折线图。

今天要创建的程序具备如下功能:

  • 从网上下载数据文件。
  • 对数据文件进行解析,并提取感兴趣的内容。
  • 根据这些数据创建PDF图形。

与前一个项目一样,原型可能没有实现这些目标。

2.有用的工具

就这个项目而言,最重要的工具是图形生成包。这样的包有很多,我选择的是ReportLab,因为它易于使用,并且提供了丰富的PDF图形和文档生成功能。如果你不想只是蜻蜓点水,可考虑使用图形包PYX(http://pyx.sf.set),其功能非常强大,并支持基于TEX排版。

要获取ReportLab包,可访问其官网http://www.reportlab.org,其中包含软件、文档和示例。你可以从这个网站下载ReportLab,也可以使用pip来安装它。安装ReportLab后,就能够导入模块reportlab了,如下所示:


注意 在这个项目中,我将演示ReportLab的一些功能,但它还有很多其他的功能。要进行更深入的学习,建议你从ReportLab网站获取用户手册。这个用户手册易于理解,涵盖的内容比这个项目全面的多。


3.准备工作

开始编程之前,需要一些用来测试程序的数据。我(很随意地)选择了有关太阳黑子的数据,这些数据可从空间天气预测中心(http://www.swpc.noaa.gov)下载。我在示例中使用的数据可在ftp://ftp.swpc.noaa.gov/pub/weekly/Predict.txt找到。

这个数据文件每周都会更新,其中包含有关太阳黑子和辐射流量的数据。下载这个文件后,就可着手解决问题了。

4.初次实现

在初次实现中,我们将以元组列表的方式将这些数据添加到源代码中,以便轻松地使用它们。下面演示了如何这样做:

完成这项工作后,来看看如何将数据转换为图形。

4.1.使用ReportLab绘图

ReportLab由很多部分组成,让你能够以多种方式生成输出。就生成PDF而言,最基本的模块是pdfgen,其中的Canvas类包含多个低级绘图方法。例如,要在名为c的Canvas上绘制直线,可调用方法c.line。

我们将使用更高级的图形框架(reportlab.graphics包及其子模块),它能让我们创建各种形状,将其添加到Drawing对象中,再将Drawing对象输出到PDF文件中。

下图是一个示例程序,它在一个100点x100点的PDF图形中央绘制字符串"Hello,world!"。这个程序的基本结构如下:创建一个指定尺寸的Drawing对象,在创建具有指定尺寸的图形元素(这里是一个String对象),然后将图形元素添加到Drawing对象中。最后,以PDF格式渲染Drawing对象,并将结果保存到文件中。

上述对renderPDF.drawToFile的调用将PDF文件保存到当前目录下的文件hello.pdf中。

构造函数String的主要参数包括x坐标和y坐标以及文本。另外,你还可指定各种属性,如字号、颜色等。在这里,我设置了参数textAnchor,它指定要将字符串的哪部分放在坐标指定的位置。

4.2.绘制折线

为绘制太阳黑子数据折线图,需要绘制一些直线。实际上,你需要绘制多条相连的直线。ReportLab提供了一个专门用来完成这种工作的类——PolyLine。

要创建折线(PolyLine对象),需要将第一个参数指定为一个坐标列表。这个列表形如[(x0, y0), (x1, y1), ...],其中每对x坐标和y坐标都指定了折线上的一个点。

要绘制折线图,必须为数据集中的每列数据绘制一条折线。这些折线上的每个点都由时间(年和月)和值(从相关列获取的太阳黑子数)组成。要获取一列的值,可使用列表推导。

pred = [row[2]for row in data]

pred将是一个列表,其中包含第3列的所有值。你可是用类似的方式来获取其他列的值(对于每行的时间,必须根据年和月来计算,如year+month/12。)

有了值和时间戳后,便可像下面这样在Drawing对象中添加折线了:

drawing.add(PolyLine(list(zip(times, pred)), strokeColor=colors.blue))

当然,并非必须设置笔画的颜色,但这样做更容易将折线区分开来。请注意,这里使用zip将时间和值合并成了元组列表。

4.3.编写原型

现在可以编写程序的第一个版本了,其源代码如图所示。

如你所见,为了正确的定位,我调整了值和时间戳。生成的图形如图所示。

虽然能够创建出管用的程序令人高兴,但这个程序显然还有改进的空间。

原文发布于微信公众号 - 小陈学Python(gh_a29b1ed16571)

原文发表时间:2018-07-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券