matplotlib实现自定义散点形状marker的3种方法
目录
- 无填充形状和填充形状
- Tex形状
- Path对象
- 使用Path模块中的Path对象
- 自定义Path对象
- 从svg格式转化为Path对象
- 参考
marker有4种类型,分别是:
- Unfilled markers: 无填充形状
- Filled markers: 填充形状
- markers created from Tex symbols: 即用tex字符串定义的形状
- created from paths:自定义的matplotlib中的Path对象即路径。
无填充形状和填充形状 使用这种形状只需给marker指定一个字符或者一个数字即可
文章图片
文章图片
Tex形状 通过自定义一个符合Latex格式的字符串复制给marker即可,因此如果想让makrer为一个数字或者单词字母或者特殊的符号便可以定义这样一个字符串
import matplotlib.pyplot as plt import numpy as np data = https://www.it610.com/article/np.random.rand(3,2)fig = plt.figure() ax = fig.add_subplot(111) markers = ["$\u266B$", r"$\frac{1}{2}$", "$\heartsuit$"]for i in range(data.shape[0]):ax.scatter(data[i,0], data[i,1], marker=markers[i], s=400) plt.show()
文章图片
Path对象 matplotlib中Path类的定义参考了图片格式svg格式的定义,具体不做阐述,可自行百度。Path对象给定制marker提供了极大的便利,可以使用Path模块中已经定义好的一些Path类供用户组合,用户也可以自定义Path类
使用Path模块中的Path对象
import matplotlib.pyplot as pltimport matplotlib.path as mpathimport numpy as npstar = mpath.Path.unit_regular_star(6)# 星型Pathcircle = mpath.Path.unit_circle()# 圆形Path # 整合两个路径对象的点verts = np.concatenate([circle.vertices, star.vertices[::-1, ...]])# 整合两个路径对象点的类型codes = np.concatenate([circle.codes, star.codes])# 根据路径点和点的类型重新生成一个新的Path对象 cut_star = mpath.Path(verts, codes)plt.plot(np.arange(10)**2, '--r', marker=cut_star, markersize=15)plt.show()
文章图片
自定义Path对象
import matplotlib.pyplot as pltimport matplotlib.path as mpathimport numpy as npcircle = mpath.Path.unit_circle()# 获得一个圆 verts_part= circle.wedge(340,220).vertices# 按逆时针从340度到220度部分圆的路径点codes_part = circle.wedge(340,220).codes# 点类型 verts_part = verts_part[1:-2]# 去除第一个点和最后两个点 codes_part = codes_part[1:-2] # 整合新的点 verts = np.concatenate([np.array([[0,-2]]), verts_part, np.array([[0,-2]])]) codes = [mpath.Path.MOVETO] + codes_part.tolist() +[mpath.Path.CLOSEPOLY] icon = mpath.Path(vertices=verts, codes=codes)plt.plot(verts[:,0], verts[:,1]) plt.show()
文章图片
plt.scatter(data[:,0], data[:,1], marker=icon, s=300, facecolor="none",edgecolors="black")plt.show()
文章图片
从svg格式转化为Path对象
既然Path类的定义起源于svg,那么引申出一个问题,能否将svg格式的图片转化为Path对象?这样我们就不用费力自己定义Path对象,而是可以用别人已经定义好的svg格式的图片转换为Path对象
答案是可以的,可以用svgpath2mpl库解析svg转化为matplotlib的Path对象
import matplotlib as mpl from svgpath2mpl import parse_pathimport xml.etree.ElementTree as etree from six import StringIO import re
# svg格式图片的svg代码svg = """"""# 解析代码 tree = etree.parse(StringIO(svg)) root = tree.getroot() width = int(re.match(r'\d+', root.attrib['width']).group())height = int(re.match(r'\d+', root.attrib['height']).group())path_elems = root.findall('.//{http://www.w3.org/2000/svg}path') # 解析出每个Path对象paths = [parse_path(elem.attrib['d']) for elem in path_elems] facecolors = [elem.attrib.get('fill', 'none') for elem in path_elems] facecolors = [c if c !="" else "none" for c in facecolors]edgecolors = [elem.attrib.get('stroke', 'none') for elem in path_elems]linewidths = [elem.attrib.get('stroke_width', 1) for elem in path_elems]
#定义旋转矩阵def rot(verts, az):#顺时针旋转rad = az / 180 * np.piverts = np.array(verts)rotMat = np.array([[np.cos(rad), -np.sin(rad)], [np.sin(rad), np.cos(rad)]])transVerts = verts.dot(rotMat)return transVerts
# 合并每个Path对象verts = paths[0].vertices codes = paths[0].codes for i in range(1,len(paths)): verts = np.concatenate([verts, paths[i].vertices])codes = np.concatenate([codes, paths[i].codes])verts = rot(verts, 180) fig = plt.figure() ax = fig.add_subplot(111) ax.plot(verts[:,0], verts[:,1], color="red")plt.show()
文章图片
# 定义解析函数 def svg2path(svg):# 解析代码 tree = etree.parse(StringIO(svg)) root = tree.getroot() path_elems = root.findall('.//{http://www.w3.org/2000/svg}path') # 解析出每个Path对象paths = [parse_path(elem.attrib['d']) for elem in path_elems] # 合并path对象verts = paths[0].vertices codes = paths[0].codes for i in range(1, len(paths)): verts = np.concatenate([verts, paths[i].vertices])codes = np.concatenate([codes, paths[i].codes])# 复原为原来的形状verts = rot(verts, 270) verts = np.fliplr(verts)# 水平翻转,镜像#verts = (verts - verts.min(0)) / (verts.max(0) - verts.min(0)) icon = mpath.Path(vertices=verts, codes=codes)return icon
svg = ["""""","""""",""""""]icons = []for s in svg:icons.append(svg2path(s))
fig = plt.figure() ax = fig.add_subplot(111) for i in range(data.shape[0]):ax.scatter(data[i,0], data[i,1], marker=icons[i], s=3000)plt.show()
文章图片
参考 https://matplotlib.org/stable/gallery/lines_bars_and_markers/marker_reference.html#sphx-glr-gallery-lines-bars-and-markers-marker-reference-py
https://nbviewer.jupyter.org/github/nvictus/svgpath2mpl/blob/master/examples/homer.ipynb
【matplotlib实现自定义散点形状marker的3种方法】到此这篇关于matplotlib实现自定义散点形状marker的3种方法的文章就介绍到这了,更多相关matplotlib 自定义散点形状marker内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- SpringBoot调用公共模块的自定义注解失效的解决
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- python自定义封装带颜色的logging模块
- java中如何实现重建二叉树
- 列出所有自定义的function和view