资讯详情

Matplotlib进阶教程:文本讲解

1a82ff01b54b3fc79ec9e33d3cee2a64.gif

回复后台【读书】

即可获取python相关电子书~

Hi,我是山月。

今我们今天解释一下,这也是这个系列的倒数第二篇。还没学过的朋友可以学。~

01

Matplotlib 图中的文本

下面介绍一下怎么做 Matplotlib 绘制和处理文本。

在这里使用以下命令 pyplot 界面和面向对象 API 中创文本:

所有这些函数都将创建并返回一个函数 Text 本例可配置各种字体等属性。

importmatplotlib.pyplotasplt  fig=plt.figure() ax=fig.add_subplot(111) fig.subplots_adjust(top=0.85)  #设置图形和子图的标题 fig.suptitle('boldfiguresuptitle',fontsize=14,fontweight='bold') ax.set_title('axestitle')  ax.set_xlabel('xlabel') ax.set_ylabel('ylabel')  #将x轴和y轴限制设置为[0,10],而不是默认值[0,1] ax.axis([0,10,0,10])  ax.text(3,8,'boxeditalicstextindatacoords',style='italic', bbox={'facecolor':'red','alpha':0.5,'pad':10})  ax.text(2,6,r'anequation:$E=mc^2$',fontsize=15)  ax.text(3,2,'unicode:InstitutfürFestk?rperphysik')  ax.text(0.95,0.01,'coloredtextinaxescoords', verticalalignment='bottom',horizontalalignment='right', transform=ax.transAxes, color='green',fontsize=15)  ax.plot([2],[1],'o') ax.annotate('annotate',xy=(2,1),xytext=(3,4), arrowprops=dict(facecolor='black',shrink=0.05))  plt.show()

效果:

可以通过 set_xlabel 和 set_ylabel 方法指定 x 轴和 y 轴的标签:

importmatplotlib.pyplotasplt importnumpyasnp  x1=np.linspace(0.0,5.0,100) y1=np.cos(2*np.pi*x1)*np.exp(-x1)  fig,ax=plt.subplots(figsize=(5,3)) fig.subplots_adjust(bottom=0.15,left=0.2) ax.plot(x1,y1) ax.set_xlabel('time[s]') ax.set_ylabel('Dampedoscillation[V]')  plt.show()

效果:

x自动放置和y标签,以清除x和y标签。

比较下图和上图,注意y标签的位置。

importmatplotlib.pyplotasplt importnumpyasnp  x1=np.linspace(0.0,5.0,100) y1=np.cos(2*np.pi*x1)*np.exp(-x1)  fig,ax=plt.subplots(figsize=(5,3)) fig.subplots_adjust(bottom=0.15,left=0.2) ax.plot(x1,y1*10000) ax.set_xlabel('time[s]') ax.set_ylabel('Dampedoscillation[V]')  plt.show()

效果:

如果要移动标签,可以指定 labelpad 关键词参数值为磅(1磅)=1/72英寸,单位与字体大小相同,12磅高为12号)。

importmatplotlib.pyplotasplt importnumpyasnp  x1=np.linspace(0.0,5.0,100) y1=np.cos(2*np.pi*x1)*np.exp(-x1)  fig,ax=plt.subplots(figsize=(5,3)) fig.subplots_adjust(bottom=0.15,left=0.2) ax.plot(x1,y1*10000) ax.set_xlabel('time[s]') ax.set_ylabel('Dampedoscillation[V]',labelpad=18)  plt.show()

效果:

所有的标签一切 Text 包括位置在内的关键字参数。

因此,我们可以手动指定标签位置,如 x轴标签放在轴的最左侧。

importmatplotlib.pyplotasplt importnumpyasnp  x1=np.linspace(0.0,5.0,100) y1=np.cos(2*np.pi*x1)*np.exp(-x1)  fig,ax=plt.subplots(figsize=(5,3)) fig.subplots_adjust(bottom=0.15,left=0.2) ax.plot(x1,y1) ax.set_xlabel('time[s]',position=(0.,1e6),horizontalalignment='left') ax.set_ylabel('Dampedoscillation[V]')  plt.show() 
   

效果:

标签也可以通过 matplotlib.font_manager.FontProperties 方法更改,或者使它作为参数添加到set_ylabel:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

font = FontProperties()
font.set_family('serif')
font.set_name('Times New Roman')
font.set_style('italic')

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('time [s]', fontsize='large', fontweight='bold')
ax.set_ylabel('Damped oscillation [V]', fontproperties=font)

plt.show()

效果:

最后,我们可以在所有文本对象中使用本机 TeX 渲染并拥有多行:

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.2, left=0.2)
ax.plot(x1, np.cumsum(y1**2))
ax.set_xlabel('time [s] \n This was a long experiment')
ax.set_ylabel(r'$\int\ Y^2\ dt\ \ [V^2 s]$')
plt.show()

效果:

子图标题的设置方式与标签大致相同,但可以通过 loc( 默认loc=center ) 关键字参数更改位置和对齐方式。

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, axs = plt.subplots(3, 1, figsize=(5, 6), tight_layout=True)
locs = ['center', 'left', 'right']
for ax, loc in zip(axs, locs):
    ax.plot(x1, y1)
    ax.set_title('Title with loc at '+loc, loc=loc)
plt.show()

效果:

标题的垂直间距通过参数pad(默认值 6.0)控制,设置不同的间距会移动标题位置。

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(top=0.8)
ax.plot(x1, y1)
ax.set_title('Vertically offset title', pad=30)
plt.show()

效果:

Axes 具有用于 ax.xaxis 和 ax.yaxis 的 matplotlib.axis.Axis 对象,其中包含轴标签如何布局的信息。

Axis 对象具有主/次刻度。

Axis可以通过Axis.set_major_locator 和 Axis.set_minor_locator 方法,使用正在绘制的数据来确定主和次刻度的位置。

还有用于格式化刻度标签的 Axis.set_major_formatter 和 Axis.set_minor_formatter 方法。

Matplotlib 会自动给我们定义基础的刻度,如第一个图。

不过我们也可以在这个基础上进行一些设置,比如重置轴限制,如第二个图。

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
axs[1].xaxis.set_ticks(np.arange(0., 8.1, 2.))
plt.show()

效果:

更改刻度的格式:

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
tickla = ['%1.2f' % tick for tick in ticks]
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_ticklabels(tickla)
axs[1].set_xlim(axs[0].get_xlim())
plt.show()

效果:

我们可以使用 matplotlib.ticker.StrMethodFormatter ( str.format() 格式字符串)或 matplotlib.ticker.FormatStrFormatter ( '%' 格式字符串)并将其传递给ax.xaxis,而不是列出所有刻度标签的列表。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
formatter = matplotlib.ticker.StrMethodFormatter('{x:1.1f}')
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_major_formatter(formatter)
axs[1].set_xlim(axs[0].get_xlim())
plt.show()

效果:

当然,我们可以使用非默认定位器来设置刻度位置:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
ticks = np.arange(0., 8.1, 2.)

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
locator = matplotlib.ticker.FixedLocator(ticks)
axs[1].xaxis.set_major_locator(locator)
axs[1].xaxis.set_major_formatter(formatter)
plt.show()

效果:

默认的格式化程序是 matplotlib.ticker.MaxNLocator:

ticker.MaxNLocator(self, nbins='auto', steps=[1, 2, 2.5, 5, 10])

steps 关键字包含一个可用于刻度值的倍数列表。

即在 steps=[1, 2, 2.5, 5, 10]) 的情况下,2、4、6 是可接受的刻度,20、40、60 或 0.2、0.4、0.6 也是如此。

但是,3、6、9 是不可接受的,因为 3 没有出现在步骤列表中。

nbins=auto 根据轴的长度使用算法来确定可接受的刻度数,但它只考虑了刻度标签的字体大小,但没有考虑刻度标签的的长度。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, axs = plt.subplots(2, 2, figsize=(8, 5), tight_layout=True)
for n, ax in enumerate(axs.flat):
    ax.plot(x1*10., y1)

formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
locator = matplotlib.ticker.MaxNLocator(nbins='auto', steps=[1, 4, 10])
axs[0, 1].xaxis.set_major_locator(locator)
axs[0, 1].xaxis.set_major_formatter(formatter)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.AutoLocator()
axs[1, 0].xaxis.set_major_formatter(formatter)
axs[1, 0].xaxis.set_major_locator(locator)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.MaxNLocator(nbins=4)
axs[1, 1].xaxis.set_major_formatter(formatter)
axs[1, 1].xaxis.set_major_locator(locator)

plt.show()

效果:

最后,我们可以使用 matplotlib.ticker.FuncFormatter 为格式化程序指定函数。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

def formatoddticks(x, pos):
    # 设置奇数刻度位置的格式
    if x % 2:
        return '%1.2f' % x
    else:
        return ''

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.plot(x1, y1)
formatter = matplotlib.ticker.FuncFormatter(formatoddticks)
locator = matplotlib.ticker.MaxNLocator(nbins=6)
ax.xaxis.set_major_formatter(formatter)
ax.xaxis.set_major_locator(locator)

plt.show()

效果:

Matplotlib 可接受 datetime.datetime 和 numpy.datetime64 对象作为绘图参数。

由于日期和时间需要特殊格式,所以它通常手动设置。

日期具有的特殊定位器和格式化程序,这在 matplotlib.dates 模块中定义了。

一个简单的例子如下:

import matplotlib.pyplot as plt
import numpy as np
import datetime

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
base = datetime.datetime(2017, 1, 1, 0, 0, 1)
time = [base + datetime.timedelta(days=x) for x in range(len(x1))]

ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()

效果:

我们可以将格式传递给 matplotlib.dates.DateFormatter。

注意29号和下个月的时间很接近,所以我们可以通过使用 dates.DayLocator 类来指定要使用的月份的日期列表。

matplotlib.dates 模块中也列出了类似的格式化程序。

import matplotlib.pyplot as plt
import numpy as np
import datetime
import matplotlib.dates as mdates

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

base = datetime.datetime(2017, 1, 1, 0, 0, 1)
time = [base + datetime.timedelta(days=x) for x in range(len(x1))]
locator = mdates.DayLocator(bymonthday=[1, 15])
formatter = mdates.DateFormatter('%b %d')

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()

效果:

02

文本属性和布局

matplotlib.text.Text 实例有多种属性,可以通过文本命令的关键字参数(例如,title()、xlabel() 和 text())进行配置。

可以使用对齐参数horizontalalignment(水平对齐)、verticalalignment(垂直对齐)和multialignment(多重对齐)来布置文本。

  • Horizontalalignment 控制文本的 x 位置参数在文本边界框的左侧、中心还是右侧。

  • verticalalignment 控制文本的 y 位置参数在文本边界框的底部、中心还是顶部。

  • multialignment,仅用于换行分隔的字符串,控制不同的行是左对齐、居中对齐还是右对齐。

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

# 在坐标系中建立一个矩形
left, width = .25, .5
bottom, height = .25, .5
right = left + width
top = bottom + height

fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])

# 轴坐标:(0,0)为左下角,(1,1)为右上角
p = patches.Rectangle(
    (left, bottom), width, height,
    fill=False, transform=ax.transAxes, clip_on=False
    )

ax.add_patch(p)

ax.text(left, bottom, 'left top',
        horizontalalignment='left',
        verticalalignment='top',
        transform=ax.transAxes)

ax.text(left, bottom, 'left bottom',
        horizontalalignment='left',
        verticalalignment='bottom',
        transform=ax.transAxes)

ax.text(right, top, 'right bottom',
        horizontalalignment='right',
        verticalalignment='bottom',
        transform=ax.transAxes)

ax.text(right, top, 'right top',
        horizontalalignment='right',
        verticalalignment='top',
        transform=ax.transAxes)

ax.text(right, bottom, 'center top',
        horizontalalignment='center',
        verticalalignment='top',
        transform=ax.transAxes)

ax.text(left, 0.5*(bottom+top), 'right center',
        horizontalalignment='right',
        verticalalignment='center',
        rotation='vertical',
        transform=ax.transAxes)

ax.text(left, 0.5*(bottom+top), 'left center',
        horizontalalignment='left',
        verticalalignment='center',
        rotation='vertical',
        transform=ax.transAxes)

ax.text(0.5*(left+right), 0.5*(bottom+top), 'middle',
        horizontalalignment='center',
        verticalalignment='center',
        fontsize=20, color='red',
        transform=ax.transAxes)

ax.text(right, 0.5*(bottom+top), 'centered',
        horizontalalignment='center',
        verticalalignment='center',
        rotation='vertical',
        transform=ax.transAxes)

ax.text(left, top, 'rotated\nwith newlines',
        horizontalalignment='center',
        verticalalignment='center',
        rotation=45,
        transform=ax.transAxes)

ax.set_axis_off()
plt.show()

效果:

默认字体由一组参数控制。

比如要设置数学表达式中的字体,可以使用以 mathtext 开头的参数。

family别名({'cursive', 'fantasy', 'monospace', 'sans', 'sans serif', 'sans-serif', 'serif'})和实际字体名称之间的映射由以下参数控制:

从 v2.0 开始,默认字体 DejaVu 包含许多西方字母的字形,但不包含其他文字,例如中文、韩文或日文。

若要将默认字体设置为支持所需码点的字体,可以将字体名称前缀为'font.family'或想要的别名列表。

matplotlib.rcParams['font.sans-serif'] = ['Source Han Sans TW', 'sans-serif']

或将其设置在 .matplotlibrc 文件中:

font.sans-serif: Source Han Sans TW, Arial, sans-serif

要控制每个artist使用的字体,可以使用上面记录的 'name'、'fontname' 或 'fontproperties' 关键字参数。

03

注释

使用 text() 可以将文本放置在轴上的任意位置。

文本的一个常见用例是对绘图的某些特征进行注释,使用annotate() 方法可以使注释变的简单。

在注释中,有两点需要考虑:被注释的位置由参数xy表示;文本的位置由参数xytext表示。

这两个参数都是(x, y)元组。

示例:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = ax.plot(t, s, lw=2)

ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )
ax.set_ylim(-2, 2)
plt.show()

效果:

在此示例中,xy位置和 xytext 位置都在数据坐标中,但你也可以通过下面的字符串指定xy和xytext的坐标系统:

如果要将文本坐标放在分数轴坐标中,可以这样做:

ax.annotate('local max', xy=(3, 1),  xycoords='data',
            xytext=(0.8, 0.95), textcoords='axes fraction',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='right', verticalalignment='top',
            )

对于物理坐标系(点或像素),原点是图形或axes的左下角。

可以在可选关键字参数 arrowprops 中提供箭头属性字典来启用从文本到注释点的箭头绘制:

示例:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111, polar=True)
r = np.arange(0, 1, 0.001)
theta = 2 * 2*np.pi * r
line, = ax.plot(theta, r, color='#ee8d18', lw=3)

ind = 800
thisr, thistheta = r[ind], theta[ind]
ax.plot([thistheta], [thisr], 'o')
ax.annotate('a polar annotation',
            xy=(thistheta, thisr),  # theta, radius
            xytext=(0.05, 0.05),    # fraction, fraction
            textcoords='figure fraction',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='left',
            verticalalignment='bottom',
            )
plt.show()

效果:

让我们从一个简单的例子开始。

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(5, 5))
ax.set_aspect(1)

x1 = -1 + np.random.randn(100)
y1 = -1 + np.random.randn(100)
x2 = 1. + np.random.randn(100)
y2 = 1. + np.random.randn(100)

ax.scatter(x1, y1, color="r")
ax.scatter(x2, y2, color="g")

bbox_props = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9)
ax.text(-2, -2, "Sample A", ha="center", va="center", size=20,
        bbox=bbox_props)
ax.text(2, 2, "Sample B", ha="center", va="center", size=20,
        bbox=bbox_props)


bbox_props = dict(boxstyle="rarrow", fc=(0.8, 0.9, 0.9), ec="b", lw=2)
t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45,
            size=15,
            bbox=bbox_props)

bb = t.get_bbox_patch()
bb.set_boxstyle("rarrow", pad=0.6)

ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)

plt.show()

效果:

pyplot 模块中的 text() 函数(或 Axes 类的 text 方法)接受 bbox 关键字参数,当给定时,会在文本周围绘制一个框。

bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="cyan", ec="b", lw=2)
t = ax.text(0, 0, "Direction", ha="center", va="center", rotation=45,
            size=15,
            bbox=bbox_props)

可以通过以下方式访问与文本关联的patch对象:

bb = t.get_bbox_patch()

返回值是一个 FancyBboxPatch 实例,并且可以像往常一样访问和修改诸如 facecolor、edgewidth 等的patch属性。

要更改框的形状,可以使用 set_boxstyle 方法。

bb.set_boxstyle("rarrow", pad=0.6)

参数是框样式的名称,其属性作为关键字参数。目前,实现了以下框样式:

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

styles = mpatch.BoxStyle.get_styles()
spacing = 1.2

figheight = (spacing * len(styles) + .5)
fig = plt.figure(figsize=(4 / 1.5, figheight / 1.5))
fontsize = 0.3 * 72

for i, stylename in enumerate(sorted(styles)):
    fig.text(0.5, (spacing * (len(styles) - i) - 0.5) / figheight, stylename,
             ha="center",
             size=fontsize,
             bbox=dict(boxstyle=stylename, fc="w", ec="k"))

plt.show()

效果:

注意,属性参数可以在样式名称中用逗号分隔。

bb.set_boxstyle("rarrow,pad=0.6")

pyplot 模块中的 annotate() 函数(或 Axes 类的 annotate 方法)也可用于绘制连接图上两点的箭头。

ax.annotate("Annotation",
            xy=(x1, y1), xycoords='data',
            xytext=(x2, y2), textcoords='offset points',
            )

这使用 textcoords 中给出的 xytext 坐标处的文本来注释 xycoords 中给出的 xy 坐标处的点。

通常,注释点在数据坐标中指定,注释文本在偏移点中指定。

通过指定 arrowprops 参数,可以选择绘制连接两点(xy 和 xytext)的箭头。

如果仅想绘制箭头,则使用空字符串作为第一个参数:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(3, 3))
ax.annotate("",
            xy=(0.2, 0.2), xycoords='data',
            xytext=(0.8, 0.8), textcoords='data',
            arrowprops=dict(arrowstyle="->",
                            connectionstyle="arc3"),
            )

plt.show()

效果:

绘制箭头图需要以下几个步骤:

  • 创建两点之间的连接路径。这由 connectionstyle 键值对控制。

  • 如果给出了patch对象(patchA和patchB),则剪切路径以避免patch。

  • 路径进一步收缩到给定的像素量(shrinkA & shrinkB)

  • 路径转换为箭头patch,由arrowstyle键值对控制。

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


fig, axs = plt.subplots(2, 2)
x1, y1 = 0.3, 0.3
x2, y2 = 0.7, 0.7

ax = axs.flat[0]
ax.plot([x1, x2], [y1, y2], ".")
el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2)
ax.add_artist(el)
ax.annotate("",
            xy=(x1, y1), xycoords='data',
            xytext=(x2, y2), textcoords='data',
            arrowprops=dict(arrowstyle="-",
                            color="0.5",
                            patchB=None,
                            shrinkB=0,
                            connectionstyle="arc3,rad=0.3",
                            ),
            )
ax.text(.05, .95, "connect", transform=ax.transAxes, ha="left", va="top")

ax = axs.flat[1]
ax.plot([x1, x2], [y1, y2], ".")
el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2)
ax.add_artist(el)
ax.annotate("",
            xy=(x1, y1), xycoords='data',
            xytext=(x2, y2), textcoords='data',
            arrowprops=dict(arrowstyle="-",
                            color="0.5",
                            patchB=el,
                            shrinkB=0,
                            connectionstyle="arc3,rad=0.3",
                            ),
            )
ax.text(.05, .95, "clip", transform=ax.transAxes, ha="left", va="top")

ax = axs.flat[2]
ax.plot([x1, x2], [y1, y2], ".")
el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2)
ax.add_artist(el)
ax.annotate("",
            xy=(x1, y1), xycoords='data',
            xytext=(x2, y2), textcoords='data',
            arrowprops=dict(arrowstyle="-",
                            color="0.5",
                            patchB=el,
                            shrinkB=5,
                            connectionstyle="arc3,rad=0.3",
                            ),
            )
ax.text(.05, .95, "shrink", transform=ax.transAxes, ha="left", va="top")

ax = axs.flat[3]
ax.plot([x1, x2], [y1, y2], ".")
el = mpatches.Ellipse((x1, y1), 0.3, 0.4, angle=30, alpha=0.2)
ax.add_artist(el)
ax.annotate("",
            xy=(x1, y1), xycoords='data',
            xytext=(x2, y2), textcoords='data',
            arrowprops=dict(arrowstyle="fancy",
                            color="0.5",
                            patchB=el,
                            shrinkB=5,
                            connectionstyle="arc3,rad=0.3",
                            ),
            )
ax.text(.05, .95, "mutate", transform=ax.transAxes, ha="left", va="top")

for ax in axs.flat:
    ax.set(xlim=(0, 1), ylim=(0, 1), xticks=[], yticks=[], aspect=1)

plt.show()

效果:

两点之间的连接路径的创建由 connectionstyle 键控制,可以使用以下样式:

请注意,angle3 和 arc3 中的“3”表示生成的路径是二次样条线段(三个控制点)。

在下面的示例中(有限地)演示了每种连接样式的行为:

import matplotlib.pyplot as plt


def demo_con_style(ax, connectionstyle):
    x1, y1 = 0.3, 0.2
    x2, y2 = 0.8, 0.6

    ax.plot([x1, x2], [y1, y2], ".")
    ax.annotate("",
                xy=(x1, y1), xycoords='data',
                xytext=(x2, y2), textcoords='data',
                arrowprops=dict(arrowstyle="->", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle=connectionstyle,
                                ),
                )

    ax.text(.05, .95, connectionstyle.replace(",", ",\n"),
            transform=ax.transAxes, ha="left", va="top")


fig, axs = plt.subplots(3, 5, figsize=(8, 4.8))
demo_con_style(axs[0, 0], "angle3,angleA=90,angleB=0")
demo_con_style(axs[1, 0], "angle3,angleA=0,angleB=90")
demo_con_style(axs[0, 1], "arc3,rad=0.")
demo_con_style(axs[1, 1], "arc3,rad=0.3")
demo_con_style(axs[2, 1], "arc3,rad=-0.3")
demo_con_style(axs[0, 2], "angle,angleA=-90,angleB=180,rad=0")
demo_con_style(axs[1, 2], "angle,angleA=-90,angleB=180,rad=5")
demo_con_style(axs[2, 2], "angle,angleA=-90,angleB=10,rad=5")
demo_con_style(axs[0, 3], "arc,angleA=-90,angleB=0,armA=30,armB=30,rad=0")
demo_con_style(axs[1, 3], "arc,angleA=-90,angleB=0,armA=30,armB=30,rad=5")
demo_con_style(axs[2, 3], "arc,angleA=-90,angleB=0,armA=0,armB=40,rad=0")
demo_con_style(axs[0, 4], "bar,fraction=0.3")
demo_con_style(axs[1, 4], "bar,fraction=-0.3")
demo_con_style(axs[2, 4], "bar,angle=180,fraction=-0.2")

for ax in axs.flat:
    ax.set(xlim=(0, 1), ylim=(0, 1), xticks=[], yticks=[], aspect=1)
fig.tight_layout(pad=0.2)

plt.show()

效果:

根据给定的箭头样式,将连接路径(剪切和收缩后)转换为箭头patch。

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

styles = mpatches.ArrowStyle.get_styles()

ncol = 2
nrow = (len(styles) + 1) // ncol
figheight = (nrow + 0.5)
fig = plt.figure(figsize=(4 * ncol / 1.5, figheight / 1.5))
fontsize = 0.2 * 70


ax = fig.add_axes([0, 0, 1, 1], frameon=False, aspect=1.)

ax.set_xlim(0, 4 * ncol)
ax.set_ylim(0, figheight)


def to_texstring(s):
    s = s.replace("<", r"$<$")
    s = s.replace(">", r"$>$")
    s = s.replace("|", r"$|$")
    return s


for i, (stylename, styleclass) in enumerate(sorted(styles.items())):
    x = 3.2 + (i // nrow) * 4
    y = (figheight - 0.7 - i % nrow)  # /figheight
    p = mpatches.Circle((x, y), 0.2)
    ax.add_patch(p)

    ax.annotate(to_texstring(stylename), (x, y),
                (x - 1.2, y),
                ha="right", va="center",
                size=fontsize,
                arrowprops=dict(arrowstyle=stylename,
                                patchB=p,
                                shrinkA=5,
                                shrinkB=5,
                                fc="k", ec="k",
                                connectionstyle="arc3,rad=-0.05",
                                ),
                bbox=dict(boxstyle="square", fc="w"))

ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)

plt.show()

效果:

某些箭头样式仅适用于生成二次样条线段的连接样式,如fancy,simple,和 wedge。

对于这些箭头样式,你必须使用“angle3”或“arc3”连接样式。

如果给出了注释字符串,则 patchA 默认设置为文本的 bbox patch。

import matplotlib.pyplot as plt


fig, ax = plt.subplots(figsize=(3, 3))

ax.annotate("Test",
            xy=(0.2, 0.2), xycoords='data',
            xytext=(0.8, 0.8), textcoords='data',
            size=20, va="center", ha="center",
            arrowprops=dict(arrowstyle="simple",
                            connectionstyle="arc3,rad=-0.2"),
            )

plt.show()

效果:

与 text 命令一样,可以使用 bbox 参数在文本周围绘制一个框。

import matplotlib.pyplot as plt


fig, ax = plt.subplots(figsize=(3, 3))

ann = ax.annotate("Test",
                  xy=(0.2, 0.2), xycoords='data',
                  xytext=(0.8, 0.8), textcoords='data',
                  size=20, va="center", ha="center",
                  bbox=dict(boxstyle="round4", fc="w"),
                  arrowprops=dict(arrowstyle="-|>",
                                  connectionstyle="arc3,rad=-0.2",
                                  fc="w"),
                  )

plt.show()

效果:

默认情况下,起点设置为文本范围的中心。

这可以通过 relpos 键值对进行调整,其中值根据文本的范围进行规范化。

例如,(0, 0) 表示左下角,(1, 1) 表示右上角。

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(3, 3))

ann = ax.annotate("Test",
                  xy=(0.2, 0.2), xycoords='data',
                  xytext=(0.8, 0.8), textcoords='data',
                  size=20, va="center", ha="center",
                  bbox=dict(boxstyle="round4", fc="w"),
                  arrowprops=dict(arrowstyle="-|>",
                                  connectionstyle="arc3,rad=0.2",
                                  relpos=(0., 0.),
                                  fc="w"),
                  )

ann = ax.annotate("Test",
                  xy=(0.2, 0.2), xycoords='data',
                  xytext=(0.8, 0.8), textcoords='data',
                  size=20, va="center", ha="center",
                  bbox=dict(boxstyle="round4", fc="w"),
                  arrowprops=dict(arrowstyle="-|>",
                                  connectionstyle="arc3,rad=-0.2",
                                  relpos=(1., 0.),
                                  fc="w"),
                  )

plt.show()

效果:

可以将某些Artist类别放置在 Axes 中的锚定位置,一个常见的例子是图例,可以使用 OffsetBox 类来创建这种类型的Artist。

mpl_toolkits.axes_grid1.anchored_artists 中提供了一些预定义的类,其他的在matplotlib.offsetbox 中。

import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText


fig, ax = plt.subplots(figsize=(3, 3))

at = AnchoredText("Figure 1a",
                  prop=dict(size=15), frameon=True, loc='upper left')
at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
ax.add_artist(at)

plt.show()

效果:

loc 关键字的含义与 legend 命令中的含义相同。

一个简单的应用是当artist(或artist集合)的大小在创建期间在创作期间已知像素大小。

例如,如果你想绘制一个固定大小为 20 像素 x 20 像素(半径 = 10 像素)的圆,可以使用 AnchoredDrawingArea。

该实例是使用绘图区域的大小(以像素为单位)创建的,并且可以将任意artist添加到绘图区域。

请注意,添加到绘图区域的artist的范围与绘图区域本身的位置无关。只有初始大小很重要。

from matplotlib.patches import Circle
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredDrawingArea

fig, ax = plt.subplots(figsize=(3, 3))

ada = AnchoredDrawingArea(40, 20, 0, 0,
                          loc='upper right', pad=0., frameon=False)
p1 = Circle((10, 10), 10)
ada.drawing_area.add_artist(p1)
p2 = Circle((30, 10), 5, fc="r")
ada.drawing_area.add_artist(p2)

ax.add_artist(ada)

plt.show()

效果:

有时,你希望你的artist可以根据数据坐标(或画布像素以外的坐标)进行缩放,你可以使用 AnchoredAuxTransformBox 类。

这与 AnchoredDrawingArea 类似,不同之处在于artist的范围是在绘制期间根据指定的转换确定的。

如椭圆在数据坐标中的宽度和高度分别为 0.1 和 0.4,并且会在axes的视图范围发生变化时自动缩放:

from matplotlib.patches import Ellipse
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredAuxTransformBox


fig, ax = plt.subplots(figsize=(3, 3))

box = AnchoredAuxTransformBox(ax.transData, loc='upper left')
el = Ellipse((0, 0), width=0.1, height=0.4, angle=30)  # in data coordinates!
box.drawing_area.add_artist(el)

ax.add_artist(box)

plt.show()

效果:

使用 HPacker 和 VPacker,你可以在图例中布置artist(事实上,这就是图例创建的方式)。

from matplotlib.patches import Ellipse
import matplotlib.pyplot as plt
from matplotlib.offsetbox import (AnchoredOffsetbox, DrawingArea, HPacker,
                                  TextArea)


fig, ax = plt.subplots(figsize=(3, 3))

box1 = TextArea(" Test : ", textprops=dict(color="k"))

box2 = DrawingArea(60, 20, 0, 0)
el1 = Ellipse((10, 10), width=16, height=5, angle=30, fc="r")
el2 = Ellipse((30, 10), width=16, height=5, angle=170, fc="g")
el3 = Ellipse((50, 10), width=16, height=5, angle=230, fc="b")
box2.add_artist(el1)
box2.add_artist(el2)
box2.add_artist(el3)

box = HPacker(children=[box1, box2],
              align="center",
              pad=0, sep=5)

anchored_box = AnchoredOffsetbox(loc='lower left',
                                 child=box, pad=0.,
                                 frameon=True,
                                 bbox_to_anchor=(0., 1.02),
                                 bbox_transform=ax.transAxes,
                                 borderpad=0.,
                                 )

ax.add_artist(anchored_box)

fig.subplots_adjust(top=0.8)
plt.show()

效果:

请注意,与图例不同的是,bbox_transform 默认设置为 IdentityTransform。

matplotlib 中的注释支持多种类型的坐标,如基本注释中所述。

对于想要更多控制的高级用户,它也支持一些其他选项。

1)转换实例

例如:

ax.annotate("Test", xy=(0.5, 0.5), xycoords=ax.transAxes)

等同于:

ax.annotate("Test", xy=(0.5, 0.5), xycoords="axes fraction")

有了这个,你可以在其他轴上注释一个点。

ax1, ax2 = subplot(121), subplot(122)
ax2.annotate("Test", xy=(0.5, 0.5), xycoords=ax1.transData,
             xytext=(0.5, 0.5), textcoords=ax2.transData,
             arrowprops=dict(arrowstyle="->"))

2)Artist实例

xy 值(或 xytext)被解释为artist的 bbox (get_window_extent 的返回值)的分数坐标。

ax1, ax2 = subplot(121), subplot(122)
ax2.annotate("Test", xy=(0.5, 0.5), xycoords=ax1.transData,
             xytext=(0.5, 0.5), textcoords=ax2.transData,
             arrowprops=dict(arrowstyle="->"))

效果:

请注意,坐标artist的范围(例子中an1)得在an2绘制之前确定。

3)返回 BboxBase 或 Transform 实例的可调用对象

如果返回一个Transform,则它与 1 相同,如果返回一个 bbox,则它与 2 相同。可调用对象应采用渲染器实例的单个参数。

例如,以下两个命令给出相同的结果:

an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1,
                  xytext=(30, 0), textcoords="offset points")
an2 = ax.annotate("Test 2", xy=(1, 0.5), xycoords=an1.get_window_extent,
                  xytext=(30, 0), textcoords="offset points")

4)两个坐标规范的元组

第一项用于 x 坐标,第二项用于 y 坐标。如:

annotate("Test", xy=(0.5, 1), xycoords=("data", "axes fraction"))

0.5 在数据坐标中,1 在标准化轴坐标中。你可以像使用元组一样使用artist或transform。

例如:

import matplotlib.pyplot as plt


fig, ax = plt.subplots(figsize=(3, 2))
an1 = ax.annotate("Test 1", xy=(0.5, 0.5), xycoords="data",
                  va="center", ha="center",
                  bbox=dict(boxstyle="round", fc="w"))

an2 = ax.annotate("Test 2", xy=(0.5, 1.), xycoords=an1,
                  xytext=(0.5, 1.1), textcoords=(an1, "axes fraction"),
                  va="bottom", ha="center",
 

标签: j30j矩形连接器ada10

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台