Python基础教程书籍案例:绘制生成PDF折线图(画副好画)【下】

上一篇教程我们完成了折线的绘制。

不过像太阳黑子活动信息这样的折线图,仅仅有折线是不够的。

示例效果:

《Python基础教程书籍案例:绘制生成PDF折线图(画副好画)【下】》
《Python基础教程书籍案例:绘制生成PDF折线图(画副好画)【下】》

实际上,我们是想完成像上图这样的一个折线图。

x轴方向标示了时间,y轴方向是每个时间段的数值。

并且,这个图是通过文件生成的。

例如,从我们下载数据的地址所指向的在线文件生成。

那么,通过文件生成一张折线图,我们需要做到以下几点:

  • 支持中文内容
  • 打开在线文件获取指定的内容
  • 绘图(创建画布、图表以及标题)
  • 生成PDF

1、导入需要用到的模块。

因为需要打开在线的文件,所以需要使用到urllib模块。

绘图以及生成PDF文件依然使用reportlab模块。

示例代码:

from reportlab.graphics.shapes import *
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.lineplots import LinePlot
from urllib.request import urlopen
from  reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

2、添加中文支持。

参考上一篇教程的方法,注册需要使用的字体。

pdfmetrics.registerFont(TTFont('msyh', 'msyh.ttf'))  # 注册要使用的字体

3、获取在线文件的数据

这里,我们可以先创建一个空列表,用于保存图表数据。

然后,通过urllib模块去获取数据,并通过循环把指定数据添加到列表中。

这里要注意,读取在线文件时,读取到的每行数据都需要解码,不然会以ASCII码的形式存在。

例如当前一行只有一个“#”,通过print()函数显示输出的话,会显示“35”这个数值。

经过解码之后的内容和我们看到的原始文档差不多,只不过都是以“b”开头(bytes类型)的字符串。

《Python基础教程书籍案例:绘制生成PDF折线图(画副好画)【下】》
《Python基础教程书籍案例:绘制生成PDF折线图(画副好画)【下】》

不过,这些文件内容有些我们需要,有些不需要。

如上图所示,不需要的内容和需要的内容区别在于:不需要的内容首位字符是“:”或者“#”。

所以,在代码中我们需要判断每一行数据的第一个字符是否“:”或“#”,不是的话再把数据添加到列表中。

最后,还要注意数据之间是空格分隔,我们需要让它们变成以逗号“,”分隔的元组。

示例代码:

data = []
for line in urlopen(r'ftp://ftp.swpc.noaa.gov/pub/weekly/Predict.txt'):  # 打开在线文件并循环读取每一行
    line = line.decode('ascii')  # 读取到的内容需要进行解码
    if line[0] not in [':', '#']:  # 判断首位字符不是指定字符之一
        data.append(line.split())  # 以逗号分隔每行内容并添加到列表

4、创建画布,并创建数值轴(y轴)和时间轴(x轴)的列表。

示例代码:

draw = Drawing(400, 240)

predict = [float(row[2]) for row in data]  # 创建预测线数值列表
high = [float(row[3]) for row in data]  # 创建最高线数值列表
low = [float(row[4]) for row in data]  # 创建最低线数值列表
times = [float(row[0]) + float(row[1]) / 12 for row in data]  # 创建时间轴数值列表

这里有一点需要注意,每一个列表推导式中的值都需要转换为float类型,不然会导致后方代码在运行时出现异常。

5、创建图表

这里我们使用LinePlot类进行图表的创建,这个类能够让我们方便的通过数据自动生成图表,而无需自己绘制。

我们要做的有以下几步:

  • 实例化LinePlot类创建图标对象
  • 为图表添加数据
  • 为图表进行属性的设置

示例代码:

chart = LinePlot()

chart.data = [tuple(zip(times, predict)), tuple(zip(times, high)), tuple(zip(times, low))]  # 混合列表数据添加到图表
chart.lines[0].strokeColor = colors.green  # 设置预测线颜色
chart.lines[1].strokeColor = colors.red  # 设置最高线颜色
chart.lines[2].strokeColor = colors.blue  # 设置最低线颜色
chart.width = 320  # 设置图表宽度
chart.height = 180  # 设置图表高度
chart.x = 40  # 设置图表整体x轴坐标
chart.y = 30  # 设置图表整体y轴坐标
chart.xValueAxis.valueStep = 1  # 设置图表时间轴步进间隔

这里也有一点要注意,添加数据时要把混合后的zip类型转换为tuple类型。

6、设置标题

标题的设置比较简单,上一篇教程中的开始部分就已经做过,如果忘记了,看一下代码中的注释即可。

示例代码:

title = String(200, 220, '太阳黑子活动信息图')  # 创建文本对象
title.fontName = 'msyh'  # 设置文本字体
title.fontSize = 14  # 设置文本字号
title.fillColor = colors.gray  # 设置文本颜色
title.textAnchor = 'middle'  # 设置文本位置的锚点

7、将图表和标题添加到画布并生成PDF文件。

draw.add(chart)
draw.add(title)
renderPDF.drawToFile(draw, 'chart02.pdf', '太阳黑子活动信息')

通过以上步骤,我们就完成了这个示例的编写。

    原文作者:NicePython
    原文地址: https://zhuanlan.zhihu.com/p/60569887
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞