注释图

以下示例显示了如何在matplotlib中注释绘图。这包括突出显示特定的兴趣点,并使用各种视觉工具来引起对这一点的关注。有关matplotlib中注释和文本工具的更完整和深入的描述,请参阅注释教程

  1. import matplotlib.pyplot as plt
  2. from matplotlib.patches import Ellipse
  3. import numpy as np
  4. from matplotlib.text import OffsetFrom

指定文本点和注释点

您必须指定注释点 xy = (x, y) 来注释此点。另外,您可以为此注释的文本位置指定文本点 xytext=(x, y)。 (可选)您可以使用xycoords和textcoords的以下字符串之一指定xy和xytext的坐标系(默认为’data’):

  1. 'figure points' : points from the lower left corner of the figure
  2. 'figure pixels' : pixels from the lower left corner of the figure
  3. 'figure fraction' : 0,0 is lower left of figure and 1,1 is upper, right
  4. 'axes points' : points from lower left corner of axes
  5. 'axes pixels' : pixels from lower left corner of axes
  6. 'axes fraction' : 0,0 is lower left of axes and 1,1 is upper right
  7. 'offset points' : Specify an offset (in points) from the xy value
  8. 'offset pixels' : Specify an offset (in pixels) from the xy value
  9. 'data' : use the axes data coordinate system

注意:对于物理坐标系(点或像素),原点是图形或轴的(底部,左侧)。

(可选)您可以通过提供箭头属性字典来指定箭头属性,该属性可以从文本绘制和箭头到注释点

有效关键点是:

  1. width : the width of the arrow in points
  2. frac : the fraction of the arrow length occupied by the head
  3. headwidth : the width of the base of the arrow head in points
  4. shrink : move the tip and base some percent away from the
  5. annotated point and text
  6. any key for matplotlib.patches.polygon (e.g., facecolor)
  1. # Create our figure and data we'll use for plotting
  2. fig, ax = plt.subplots(figsize=(3, 3))
  3. t = np.arange(0.0, 5.0, 0.01)
  4. s = np.cos(2*np.pi*t)
  5. # Plot a line and add some simple annotations
  6. line, = ax.plot(t, s)
  7. ax.annotate('figure pixels',
  8. xy=(10, 10), xycoords='figure pixels')
  9. ax.annotate('figure points',
  10. xy=(80, 80), xycoords='figure points')
  11. ax.annotate('figure fraction',
  12. xy=(.025, .975), xycoords='figure fraction',
  13. horizontalalignment='left', verticalalignment='top',
  14. fontsize=20)
  15. # The following examples show off how these arrows are drawn.
  16. ax.annotate('point offset from data',
  17. xy=(2, 1), xycoords='data',
  18. xytext=(-15, 25), textcoords='offset points',
  19. arrowprops=dict(facecolor='black', shrink=0.05),
  20. horizontalalignment='right', verticalalignment='bottom')
  21. ax.annotate('axes fraction',
  22. xy=(3, 1), xycoords='data',
  23. xytext=(0.8, 0.95), textcoords='axes fraction',
  24. arrowprops=dict(facecolor='black', shrink=0.05),
  25. horizontalalignment='right', verticalalignment='top')
  26. # You may also use negative points or pixels to specify from (right, top).
  27. # E.g., (-10, 10) is 10 points to the left of the right side of the axes and 10
  28. # points above the bottom
  29. ax.annotate('pixel offset from axes fraction',
  30. xy=(1, 0), xycoords='axes fraction',
  31. xytext=(-20, 20), textcoords='offset pixels',
  32. horizontalalignment='right',
  33. verticalalignment='bottom')
  34. ax.set(xlim=(-1, 5), ylim=(-3, 5))

注释图示例

使用多个坐标系和轴类型

您可以在不同位置和坐标系中指定xypoint和xytext,也可以选择打开连接线并使用标记标记点。 注释也适用于极轴。

在下面的示例中,xy点是本机坐标(xycoords默认为’data’)。对于极轴,这是在(θ,半径)空间中。示例中的文本放在小数字坐标系中。文本关键字args如水平和垂直对齐被尊重。

  1. fig, ax = plt.subplots(subplot_kw=dict(projection='polar'), figsize=(3, 3))
  2. r = np.arange(0, 1, 0.001)
  3. theta = 2*2*np.pi*r
  4. line, = ax.plot(theta, r)
  5. ind = 800
  6. thisr, thistheta = r[ind], theta[ind]
  7. ax.plot([thistheta], [thisr], 'o')
  8. ax.annotate('a polar annotation',
  9. xy=(thistheta, thisr), # theta, radius
  10. xytext=(0.05, 0.05), # fraction, fraction
  11. textcoords='figure fraction',
  12. arrowprops=dict(facecolor='black', shrink=0.05),
  13. horizontalalignment='left',
  14. verticalalignment='bottom')
  15. # You can also use polar notation on a cartesian axes. Here the native
  16. # coordinate system ('data') is cartesian, so you need to specify the
  17. # xycoords and textcoords as 'polar' if you want to use (theta, radius).
  18. el = Ellipse((0, 0), 10, 20, facecolor='r', alpha=0.5)
  19. fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
  20. ax.add_artist(el)
  21. el.set_clip_box(ax.bbox)
  22. ax.annotate('the top',
  23. xy=(np.pi/2., 10.), # theta, radius
  24. xytext=(np.pi/3, 20.), # theta, radius
  25. xycoords='polar',
  26. textcoords='polar',
  27. arrowprops=dict(facecolor='black', shrink=0.05),
  28. horizontalalignment='left',
  29. verticalalignment='bottom',
  30. clip_on=True) # clip to the axes bounding box
  31. ax.set(xlim=[-20, 20], ylim=[-20, 20])

注释图示例2

注释图示例3

自定义箭头和气泡样式

xytext和注释点之间的箭头以及覆盖注释文本的气泡可高度自定义。 下面是一些参数选项以及它们的结果输出。

  1. fig, ax = plt.subplots(figsize=(8, 5))
  2. t = np.arange(0.0, 5.0, 0.01)
  3. s = np.cos(2*np.pi*t)
  4. line, = ax.plot(t, s, lw=3)
  5. ax.annotate('straight',
  6. xy=(0, 1), xycoords='data',
  7. xytext=(-50, 30), textcoords='offset points',
  8. arrowprops=dict(arrowstyle="->"))
  9. ax.annotate('arc3,\nrad 0.2',
  10. xy=(0.5, -1), xycoords='data',
  11. xytext=(-80, -60), textcoords='offset points',
  12. arrowprops=dict(arrowstyle="->",
  13. connectionstyle="arc3,rad=.2"))
  14. ax.annotate('arc,\nangle 50',
  15. xy=(1., 1), xycoords='data',
  16. xytext=(-90, 50), textcoords='offset points',
  17. arrowprops=dict(arrowstyle="->",
  18. connectionstyle="arc,angleA=0,armA=50,rad=10"))
  19. ax.annotate('arc,\narms',
  20. xy=(1.5, -1), xycoords='data',
  21. xytext=(-80, -60), textcoords='offset points',
  22. arrowprops=dict(arrowstyle="->",
  23. connectionstyle="arc,angleA=0,armA=40,angleB=-90,armB=30,rad=7"))
  24. ax.annotate('angle,\nangle 90',
  25. xy=(2., 1), xycoords='data',
  26. xytext=(-70, 30), textcoords='offset points',
  27. arrowprops=dict(arrowstyle="->",
  28. connectionstyle="angle,angleA=0,angleB=90,rad=10"))
  29. ax.annotate('angle3,\nangle -90',
  30. xy=(2.5, -1), xycoords='data',
  31. xytext=(-80, -60), textcoords='offset points',
  32. arrowprops=dict(arrowstyle="->",
  33. connectionstyle="angle3,angleA=0,angleB=-90"))
  34. ax.annotate('angle,\nround',
  35. xy=(3., 1), xycoords='data',
  36. xytext=(-60, 30), textcoords='offset points',
  37. bbox=dict(boxstyle="round", fc="0.8"),
  38. arrowprops=dict(arrowstyle="->",
  39. connectionstyle="angle,angleA=0,angleB=90,rad=10"))
  40. ax.annotate('angle,\nround4',
  41. xy=(3.5, -1), xycoords='data',
  42. xytext=(-70, -80), textcoords='offset points',
  43. size=20,
  44. bbox=dict(boxstyle="round4,pad=.5", fc="0.8"),
  45. arrowprops=dict(arrowstyle="->",
  46. connectionstyle="angle,angleA=0,angleB=-90,rad=10"))
  47. ax.annotate('angle,\nshrink',
  48. xy=(4., 1), xycoords='data',
  49. xytext=(-60, 30), textcoords='offset points',
  50. bbox=dict(boxstyle="round", fc="0.8"),
  51. arrowprops=dict(arrowstyle="->",
  52. shrinkA=0, shrinkB=10,
  53. connectionstyle="angle,angleA=0,angleB=90,rad=10"))
  54. # You can pass an empty string to get only annotation arrows rendered
  55. ann = ax.annotate('', xy=(4., 1.), xycoords='data',
  56. xytext=(4.5, -1), textcoords='data',
  57. arrowprops=dict(arrowstyle="<->",
  58. connectionstyle="bar",
  59. ec="k",
  60. shrinkA=5, shrinkB=5))
  61. ax.set(xlim=(-1, 5), ylim=(-4, 3))
  62. # We'll create another figure so that it doesn't get too cluttered
  63. fig, ax = plt.subplots()
  64. el = Ellipse((2, -1), 0.5, 0.5)
  65. ax.add_patch(el)
  66. ax.annotate('$->$',
  67. xy=(2., -1), xycoords='data',
  68. xytext=(-150, -140), textcoords='offset points',
  69. bbox=dict(boxstyle="round", fc="0.8"),
  70. arrowprops=dict(arrowstyle="->",
  71. patchB=el,
  72. connectionstyle="angle,angleA=90,angleB=0,rad=10"))
  73. ax.annotate('arrow\nfancy',
  74. xy=(2., -1), xycoords='data',
  75. xytext=(-100, 60), textcoords='offset points',
  76. size=20,
  77. # bbox=dict(boxstyle="round", fc="0.8"),
  78. arrowprops=dict(arrowstyle="fancy",
  79. fc="0.6", ec="none",
  80. patchB=el,
  81. connectionstyle="angle3,angleA=0,angleB=-90"))
  82. ax.annotate('arrow\nsimple',
  83. xy=(2., -1), xycoords='data',
  84. xytext=(100, 60), textcoords='offset points',
  85. size=20,
  86. # bbox=dict(boxstyle="round", fc="0.8"),
  87. arrowprops=dict(arrowstyle="simple",
  88. fc="0.6", ec="none",
  89. patchB=el,
  90. connectionstyle="arc3,rad=0.3"))
  91. ax.annotate('wedge',
  92. xy=(2., -1), xycoords='data',
  93. xytext=(-100, -100), textcoords='offset points',
  94. size=20,
  95. # bbox=dict(boxstyle="round", fc="0.8"),
  96. arrowprops=dict(arrowstyle="wedge,tail_width=0.7",
  97. fc="0.6", ec="none",
  98. patchB=el,
  99. connectionstyle="arc3,rad=-0.3"))
  100. ann = ax.annotate('bubble,\ncontours',
  101. xy=(2., -1), xycoords='data',
  102. xytext=(0, -70), textcoords='offset points',
  103. size=20,
  104. bbox=dict(boxstyle="round",
  105. fc=(1.0, 0.7, 0.7),
  106. ec=(1., .5, .5)),
  107. arrowprops=dict(arrowstyle="wedge,tail_width=1.",
  108. fc=(1.0, 0.7, 0.7), ec=(1., .5, .5),
  109. patchA=None,
  110. patchB=el,
  111. relpos=(0.2, 0.8),
  112. connectionstyle="arc3,rad=-0.1"))
  113. ann = ax.annotate('bubble',
  114. xy=(2., -1), xycoords='data',
  115. xytext=(55, 0), textcoords='offset points',
  116. size=20, va="center",
  117. bbox=dict(boxstyle="round", fc=(1.0, 0.7, 0.7), ec="none"),
  118. arrowprops=dict(arrowstyle="wedge,tail_width=1.",
  119. fc=(1.0, 0.7, 0.7), ec="none",
  120. patchA=None,
  121. patchB=el,
  122. relpos=(0.2, 0.5)))
  123. ax.set(xlim=(-1, 5), ylim=(-5, 3))

注释图示例4

注释图示例5

更多坐标系的例子

下面我们将展示几个坐标系的例子,以及如何指定注释的位置。

  1. fig, (ax1, ax2) = plt.subplots(1, 2)
  2. bbox_args = dict(boxstyle="round", fc="0.8")
  3. arrow_args = dict(arrowstyle="->")
  4. # Here we'll demonstrate the extents of the coordinate system and how
  5. # we place annotating text.
  6. ax1.annotate('figure fraction : 0, 0', xy=(0, 0), xycoords='figure fraction',
  7. xytext=(20, 20), textcoords='offset points',
  8. ha="left", va="bottom",
  9. bbox=bbox_args,
  10. arrowprops=arrow_args)
  11. ax1.annotate('figure fraction : 1, 1', xy=(1, 1), xycoords='figure fraction',
  12. xytext=(-20, -20), textcoords='offset points',
  13. ha="right", va="top",
  14. bbox=bbox_args,
  15. arrowprops=arrow_args)
  16. ax1.annotate('axes fraction : 0, 0', xy=(0, 0), xycoords='axes fraction',
  17. xytext=(20, 20), textcoords='offset points',
  18. ha="left", va="bottom",
  19. bbox=bbox_args,
  20. arrowprops=arrow_args)
  21. ax1.annotate('axes fraction : 1, 1', xy=(1, 1), xycoords='axes fraction',
  22. xytext=(-20, -20), textcoords='offset points',
  23. ha="right", va="top",
  24. bbox=bbox_args,
  25. arrowprops=arrow_args)
  26. # It is also possible to generate draggable annotations
  27. an1 = ax1.annotate('Drag me 1', xy=(.5, .7), xycoords='data',
  28. #xytext=(.5, .7), textcoords='data',
  29. ha="center", va="center",
  30. bbox=bbox_args,
  31. #arrowprops=arrow_args
  32. )
  33. an2 = ax1.annotate('Drag me 2', xy=(.5, .5), xycoords=an1,
  34. xytext=(.5, .3), textcoords='axes fraction',
  35. ha="center", va="center",
  36. bbox=bbox_args,
  37. arrowprops=dict(patchB=an1.get_bbox_patch(),
  38. connectionstyle="arc3,rad=0.2",
  39. **arrow_args))
  40. an1.draggable()
  41. an2.draggable()
  42. an3 = ax1.annotate('', xy=(.5, .5), xycoords=an2,
  43. xytext=(.5, .5), textcoords=an1,
  44. ha="center", va="center",
  45. bbox=bbox_args,
  46. arrowprops=dict(patchA=an1.get_bbox_patch(),
  47. patchB=an2.get_bbox_patch(),
  48. connectionstyle="arc3,rad=0.2",
  49. **arrow_args))
  50. # Finally we'll show off some more complex annotation and placement
  51. text = ax2.annotate('xy=(0, 1)\nxycoords=("data", "axes fraction")',
  52. xy=(0, 1), xycoords=("data", 'axes fraction'),
  53. xytext=(0, -20), textcoords='offset points',
  54. ha="center", va="top",
  55. bbox=bbox_args,
  56. arrowprops=arrow_args)
  57. ax2.annotate('xy=(0.5, 0)\nxycoords=artist',
  58. xy=(0.5, 0.), xycoords=text,
  59. xytext=(0, -20), textcoords='offset points',
  60. ha="center", va="top",
  61. bbox=bbox_args,
  62. arrowprops=arrow_args)
  63. ax2.annotate('xy=(0.8, 0.5)\nxycoords=ax1.transData',
  64. xy=(0.8, 0.5), xycoords=ax1.transData,
  65. xytext=(10, 10),
  66. textcoords=OffsetFrom(ax2.bbox, (0, 0), "points"),
  67. ha="left", va="bottom",
  68. bbox=bbox_args,
  69. arrowprops=arrow_args)
  70. ax2.set(xlim=[-2, 2], ylim=[-2, 2])
  71. plt.show()

注释图示例6

下载这个示例