简介
在本实验中,我们将演示如何在 Matplotlib 的饼图中使用过滤效果。我们将借用 pie_demo.py 中的饼图绘制代码,并为图表添加过滤效果。过滤效果仅在你的 SVG 渲染器支持时才有效。
虚拟机提示
虚拟机启动完成后,点击左上角切换到笔记本标签页,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。
创建饼图
我们将为饼图创建一个正方形图形和坐标轴。我们将定义图表的标签和比例。我们还将设置饼图切片的突出显示值。最后,我们将使用定义的参数绘制饼图。
import matplotlib.pyplot as plt
from matplotlib.patches import Shadow
fig = plt.figure(figsize=(6, 6))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]
explode = (0, 0.05, 0, 0)
pies = ax.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%')
for w in pies[0]:
w.set_gid(w.get_label())
w.set_edgecolor("none")
for w in pies[0]:
s = Shadow(w, -0.01, -0.01)
s.set_gid(w.get_gid() + "_shadow")
s.set_zorder(w.get_zorder() - 0.1)
ax.add_patch(s)
plt.show()
将图表另存为 SVG 格式
我们将使用 io 和 xml.etree.ElementTree 模块把饼图保存为 SVG 文件。我们将使用高斯模糊和光照效果来定义阴影的滤镜定义。光照滤镜是从 http://www.w3.org/TR/SVG/filters.html 复制而来的。我们将使用 Inkscape 和 Firefox3 来测试该滤镜,但请注意 Inkscape 的导出功能可能不支持它。
import io
import xml.etree.ElementTree as ET
f = io.BytesIO()
plt.savefig(f, format="svg")
filter_def = """
<defs xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'>
<filter id='dropshadow' height='1.2' width='1.2'>
<feGaussianBlur result='blur' stdDeviation='2'/>
</filter>
<filter id='MyFilter' filterUnits='objectBoundingBox'
x='0' y='0' width='1' height='1'>
<feGaussianBlur in='SourceAlpha' stdDeviation='4%' result='blur'/>
<feOffset in='blur' dx='4%' dy='4%' result='offsetBlur'/>
<feSpecularLighting in='blur' surfaceScale='5' specularConstant='.75'
specularExponent='20' lighting-color='#bbbbbb' result='specOut'>
<fePointLight x='-5000%' y='-10000%' z='20000%'/>
</feSpecularLighting>
<feComposite in='specOut' in2='SourceAlpha'
operator='in' result='specOut'/>
<feComposite in='SourceGraphic' in2='specOut' operator='arithmetic'
k1='0' k2='1' k3='1' k4='0'/>
</filter>
</defs>
"""
tree, xmlid = ET.XMLID(f.getvalue())
tree.insert(0, ET.XML(filter_def))
for i, pie_name in enumerate(labels):
pie = xmlid[pie_name]
pie.set("filter", 'url(#MyFilter)')
shadow = xmlid[pie_name + "_shadow"]
shadow.set("filter", 'url(#dropshadow)')
fn = "svg_filter_pie.svg"
print(f"Saving '{fn}'")
ET.ElementTree(tree).write(fn)
查看带有过滤效果的饼图
我们将查看应用了过滤效果的饼图。我们将使用 Inkscape 打开 SVG 文件并查看带有过滤效果的饼图。
使用不同滤镜修改饼图
我们可以通过更改滤镜定义,使用不同的滤镜来修改饼图。我们可以尝试不同的滤镜以实现不同的视觉效果。
filter_def = """
<defs xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'>
<filter id='dropshadow' height='1.2' width='1.2'>
<feGaussianBlur result='blur' stdDeviation='2'/>
</filter>
<filter id='MyFilter2' filterUnits='objectBoundingBox'
x='0' y='0' width='1' height='1'>
<feGaussianBlur in='SourceAlpha' stdDeviation='4%' result='blur'/>
<feOffset in='blur' dx='4%' dy='4%' result='offsetBlur'/>
<feSpecularLighting in='blur' surfaceScale='5' specularConstant='.75'
specularExponent='20' lighting-color='#bbbbbb' result='specOut'>
<fePointLight x='50%' y='50%' z='5000%'/>
</feSpecularLighting>
<feComposite in='specOut' in2='SourceAlpha'
operator='in' result='specOut'/>
<feComposite in='SourceGraphic' in2='specOut' operator='arithmetic'
k1='0' k2='1' k3='1' k4='0'/>
</filter>
</defs>
"""
tree, xmlid = ET.XMLID(f.getvalue())
tree.insert(0, ET.XML(filter_def))
for i, pie_name in enumerate(labels):
pie = xmlid[pie_name]
pie.set("filter", 'url(#MyFilter2)')
shadow = xmlid[pie_name + "_shadow"]
shadow.set("filter", 'url(#dropshadow)')
fn = "svg_filter_pie2.svg"
print(f"Saving '{fn}'")
ET.ElementTree(tree).write(fn)
总结
在本实验中,我们学习了如何在 Matplotlib 的饼图中使用过滤效果。我们创建了一个饼图,将其保存为 SVG 文件,并对该图表应用了过滤效果。我们还使用不同的滤镜修改了饼图,以实现不同的视觉效果。