且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用 matplotlib 使绘图的 xtick 标签成为简单的绘图?

更新时间:2023-02-20 16:26:49

我会删除刻度标签并将文本替换为 ,并在其他单元中定义位置和大小(轴、图形或显示).

如果您有要用于符号的特定图像文件,您可以使用 BboxImage 类来创建要添加到轴而不是补丁的艺术家.例如,我使用以下脚本制作了一个简单的图标:

将 matplotlib.pyplot 导入为 pltfig = plt.figure(figsize=(1,1),dpi=400)ax = fig.add_axes([0,0,1,1],frameon=False)ax.set_axis_off()ax.plot(范围(10),线宽=32)ax.plot(range(9,-1,-1),linewidth=32)fig.savefig('thumb.png')

制作这张图片:

然后我在我想要刻度标签和我想要的大小的位置创建了一个 BboxImage:

lowerCorner = ax.transData.transform((.8,TICKYPOS-.2))upperCorner = ax.transData.transform((1.2,TICKYPOS+.2))bbox_image = BboxImage(Bbox([lowerCorner[0],下角[1],上角[0],上角[1],]),标准 = 无,原点=无,clip_on=假,)

注意到我如何使用 transData 转换将数据单位转换为显示单位,这在 Bbox 的定义中是必需的.

现在我使用 imread 例程读取图像,并将其结果(一个 numpy 数组)设置为 bbox_image 的数据并将艺术家添加到轴:

bbox_image.set_data(imread('thumb.png'))ax.add_artist(bbox_image)

这会产生一个更新的数字:

如果您直接使用图像,请确保导入所需的类和方法:

from matplotlib.image import BboxImage,imread从 matplotlib.transforms 导入 Bbox

Instead of words or numbers being the tick labels of the x axis, I want to draw a simple drawing (made of lines and circles) as the label for each x tick. Is this possible? If so, what is the best way to go about it in matplotlib?

I would remove the tick labels and replace the text with patches. Here is a brief example of performing this task:

import matplotlib.pyplot as plt
import matplotlib.patches as patches


# define where to put symbols vertically
TICKYPOS = -.6

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))

# set ticks where your images will be
ax.get_xaxis().set_ticks([2,4,6,8])
# remove tick labels
ax.get_xaxis().set_ticklabels([])


# add a series of patches to serve as tick labels
ax.add_patch(patches.Circle((2,TICKYPOS),radius=.2,
                            fill=True,clip_on=False))
ax.add_patch(patches.Circle((4,TICKYPOS),radius=.2,
                            fill=False,clip_on=False))
ax.add_patch(patches.Rectangle((6-.1,TICKYPOS-.05),.2,.2,
                               fill=True,clip_on=False))
ax.add_patch(patches.Rectangle((8-.1,TICKYPOS-.05),.2,.2,
                               fill=False,clip_on=False))

This results in the following figure:

It is key to set clip_on to False, otherwise patches outside the axes will not be shown. The coordinates and sizes (radius, width, height, etc.) of the patches will depend on where your axes is in the figure. For example, if you are considering doing this with subplots, you will need to be sensitive of the patches placement so as to not overlap any other axes. It may be worth your time investigating Transformations, and defining the positions and sizes in an other unit (Axes, Figure or display).

If you have specific image files that you want to use for the symbols, you can use the BboxImage class to create artists to be added to the axes instead of patches. For example I made a simple icon with the following script:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(1,1),dpi=400)
ax = fig.add_axes([0,0,1,1],frameon=False)
ax.set_axis_off()

ax.plot(range(10),linewidth=32)
ax.plot(range(9,-1,-1),linewidth=32)

fig.savefig('thumb.png')

producing this image:

Then I created a BboxImage at the location I want the tick label and of the size I want:

lowerCorner = ax.transData.transform((.8,TICKYPOS-.2))
upperCorner = ax.transData.transform((1.2,TICKYPOS+.2))

bbox_image = BboxImage(Bbox([lowerCorner[0],
                             lowerCorner[1],
                             upperCorner[0],
                             upperCorner[1],
                             ]),
                       norm = None,
                       origin=None,
                       clip_on=False,
                       )

Noticed how I used the transData transformation to convert from data units to display units, which are required in the definition of the Bbox.

Now I read in the image using the imread routine, and set it's results (a numpy array) to the data of bbox_image and add the artist to the axes:

bbox_image.set_data(imread('thumb.png'))
ax.add_artist(bbox_image)

This results in an updated figure:

If you do directly use images, make sure to import the required classes and methods:

from matplotlib.image import BboxImage,imread
from matplotlib.transforms import Bbox