一个基于canvas的简洁的Python可视化库:toyplot

简介

toyplot是一个基于canvas的简洁的Python可视化库,还在发展中,目前是0.19版;
打印标准图,有一定交互性,底层是canvas,易于在前端使用分享;
在notebook中的渲染,在其他环境中的内嵌做得挺好;qt等GUI环境支持好;
用css的写法配置样式,目前这个库在gtihub上有400余个star。

绘图框架:

1
2
3
4
5
import toyplot
canvas = toyplot.Canvas() #不写前面canvas不出图
axes = canvas.cartesian()
mark = axes.plot(df['y'], style={"stroke":"#1EAFAE",
"stroke-dasharray":"2, 2"}) #支持css的style

0-908-13-01-1-toyplot-fwk

画布+坐标系统+映射类型

With Toyplot, a figure always consists of three parts:

  • A canvas
  • One or more sets of coordinate systems added to the canvas.
  • One or more marks added to the axes.

详解:

cartesian 笛卡尔坐标系
只传y的数,x会默认使用range(0,len(y))

以上语句也可以用连缀写法写为:
···toyplot.Canvas().cartesian().plot(y)

axes.plot(x, series) 传x,传y,设置样式;
图形默认更好地展示,y轴不默认从0开始
css样式写法,在plot对象里用
多条线就在axes多调用

多条线并设置样式 toyplot

多条曲线也可以写 mark = axes.plot(x, series) #series = numpy.column_stack((y1, y2, y3))

bars 不是bar

1
2
3
canvas = toyplot.Canvas()
axes = canvas.cartesian()
mark = axes.bars(df['y'])

【bar+line】 (图层顺序,语句顺序对应图层顺序,举例,在前在后)

0-908-13-01-3-toyplot-bar+line

bar并且设置文本标签(会讲坐标映射,分类变量的处理)
(ValueError: could not convert string to float: ‘Mon.’)

设置文本角度 和上面的图对比一下

1
2
3
4
canvas = toyplot.Canvas()
axes = canvas.cartesian()
yz=[(i,j) for i,j in zip(y,z)]
mark1 = axes.bars(yz) #注意格式,是[(y1,z1),] 不是[y,z]

堆叠柱 stackbar

设置标题及文本标签,双轴

1
2
3
4
5
6
7
canvas = toyplot.Canvas()
axes = canvas.cartesian(label="双轴demo",xlabel="Weekday",ylabel="Y",ymin=0)
axes.x.ticks.locator = toyplot.locator.Explicit(labels=df['x']) #横轴文本标签
mark1 = axes.bars(y)
axes2 = axes.share("x",ylabel="H") #共享一套x轴开双轴
mark2=axes2.plot(h, style={"stroke":"#1EAFAE"})
axes2.y.spine.style = {"stroke":"#1EAFAE"}

双轴 share-axes

分面

1
2
3
4
5
canvas = toyplot.Canvas(600, 300)
axes = canvas.cartesian(grid=(1, 2, 0))
mark = axes.plot(y)
axes = canvas.cartesian(grid=(1, 2, 1))
mark = axes.plot(z)

分面 toyplot-grid

grid

支持的图形目前挺有限,fill

椭圆

作用:散点+椭圆边形成密度效果

toyplot.plot(y) 在matixe里说到
输入矩阵

两种写法;
但matrix就是属于toyplot的,目前写axes.matrix(mtx) 会报错说'Cartesian' object has no attribute 'matrix',所以mat只有一种写法,其他有两种;

交互及sav csv 方便数据交换
【矩阵图 动图,效果不是特别好,需要剪一下再说】
【目前mp4在d3的PPT里】

1
2
3
4
5
#椭圆
canvas = toyplot.Canvas()

axes = canvas.cartesian(aspect="fit-range")
axes.ellipse(0, 0, 5, 2, 45); # [x,y] 半长轴,半短轴,旋转角度
1
2
3
4
5
6
canvas = toyplot.Canvas(width=800, height=400)
axes = canvas.cartesian(grid=(1, 2, 0),label="正常椭圆")
axes.ellipse(20, 15, 20, 5, 30,style={"stroke": "black"
,"fill":"#1EAFAE","opacity":0.7})
axes = canvas.cartesian(yscale="log",grid=(1, 2, 1), label="对数坐标轴椭圆效果")
axes.ellipse(20, 15, 20, 5, 30) #把y做对数变换

toyplot ellipse

关系图

toyplot.graph(s,t)

1
2
3
sources = ["A", "B", "C", "C"]
targets = ["B", "D", "B", "A"]
toyplot.graph(sources, targets)
1
2
layout = toyplot.layout.FruchtermanReingold(edges=toyplot.layout.CurvedEdges())
toyplot.graph(edges, layout=layout, width=500)

toyplot graph

设置节点的形状(如变成矩形)、颜色、边的样式(如虚线)、边的文本标签、指向 都能做到
节点颜色根据数值大小染色

目前没有pie
图片 toyplot.image(image, width=300) 结合PIL.Image

1
2
3
4
5
import PIL.Image
import toyplot

image = PIL.Image.open("../artwork/toyplot.png")
canvas, mark = toyplot.image(image, width=300)

动画 canvas.frames 逐帧动画

1
2
3
4
5
6
7
8
9
10
canvas = toyplot.Canvas(300, 300)
axes = canvas.cartesian()
mark = axes.scatterplot(y, size=10)

for frame in canvas.frames(len(y) + 1): #动画帧
if frame.number == 0:
for i in range(len(y)):
frame.set_datum_style(mark, 0, i, style={"opacity":0.1})
else:
frame.set_datum_style(mark, 0, frame.number - 1, style={"opacity":1.0})

输出

1
2
import toyplot.pdf
toyplot.pdf.render(canvas, "figure1.pdf")

类似的有:

  • toyplot.png.render(canvas, “figure1.png”)
  • toyplot.html.render(canvas, “figure1.html”)

svg就复杂一些了,毕竟是需要canvas转svg存储。

1
2
3
4
5
svg = toyplot.svg.render(canvas)
svg.attrib["class"] = "MyCustomClass"
import xml.etree.ElementTree as xml
with open("figure1.svg", "wb") as file:
file.write(xml.tostring(svg))

总结

把简介再重复一下

toyplot是一个基于canvas的简洁的Python可视化库,还在发展中,目前是0.19版;
可能因为还不够完善,中文教程和介绍文章很少,几乎找不到详细的介绍文章;

参考资料