图例(Legend)演示

在Matplotlib中绘制图例。

在Matplotlib中有很多方法可以创建和自定义图例。 下面我们将展示一些如何操作的示例。

首先,我们将展示如何为特定线条制作图例。

  1. import matplotlib.pyplot as plt
  2. import matplotlib.collections as mcol
  3. from matplotlib.legend_handler import HandlerLineCollection, HandlerTuple
  4. from matplotlib.lines import Line2D
  5. import numpy as np
  6. t1 = np.arange(0.0, 2.0, 0.1)
  7. t2 = np.arange(0.0, 2.0, 0.01)
  8. fig, ax = plt.subplots()
  9. # note that plot returns a list of lines. The "l1, = plot" usage
  10. # extracts the first element of the list into l1 using tuple
  11. # unpacking. So l1 is a Line2D instance, not a sequence of lines
  12. l1, = ax.plot(t2, np.exp(-t2))
  13. l2, l3 = ax.plot(t2, np.sin(2 * np.pi * t2), '--o', t1, np.log(1 + t1), '.')
  14. l4, = ax.plot(t2, np.exp(-t2) * np.sin(2 * np.pi * t2), 's-.')
  15. ax.legend((l2, l4), ('oscillatory', 'damped'), loc='upper right', shadow=True)
  16. ax.set_xlabel('time')
  17. ax.set_ylabel('volts')
  18. ax.set_title('Damped oscillation')
  19. plt.show()

图例示例

接下来,我们将演示绘制更复杂的标签。

  1. x = np.linspace(0, 1)
  2. fig, (ax0, ax1) = plt.subplots(2, 1)
  3. # Plot the lines y=x**n for n=1..4.
  4. for n in range(1, 5):
  5. ax0.plot(x, x**n, label="n={0}".format(n))
  6. leg = ax0.legend(loc="upper left", bbox_to_anchor=[0, 1],
  7. ncol=2, shadow=True, title="Legend", fancybox=True)
  8. leg.get_title().set_color("red")
  9. # Demonstrate some more complex labels.
  10. ax1.plot(x, x**2, label="multi\nline")
  11. half_pi = np.linspace(0, np.pi / 2)
  12. ax1.plot(np.sin(half_pi), np.cos(half_pi), label=r"$\frac{1}{2}\pi$")
  13. ax1.plot(x, 2**(x**2), label="$2^{x^2}$")
  14. ax1.legend(shadow=True, fancybox=True)
  15. plt.show()

图例示例2

在这里,我们将图例附加到更复杂的图上。

  1. fig, axes = plt.subplots(3, 1, constrained_layout=True)
  2. top_ax, middle_ax, bottom_ax = axes
  3. top_ax.bar([0, 1, 2], [0.2, 0.3, 0.1], width=0.4, label="Bar 1",
  4. align="center")
  5. top_ax.bar([0.5, 1.5, 2.5], [0.3, 0.2, 0.2], color="red", width=0.4,
  6. label="Bar 2", align="center")
  7. top_ax.legend()
  8. middle_ax.errorbar([0, 1, 2], [2, 3, 1], xerr=0.4, fmt="s", label="test 1")
  9. middle_ax.errorbar([0, 1, 2], [3, 2, 4], yerr=0.3, fmt="o", label="test 2")
  10. middle_ax.errorbar([0, 1, 2], [1, 1, 3], xerr=0.4, yerr=0.3, fmt="^",
  11. label="test 3")
  12. middle_ax.legend()
  13. bottom_ax.stem([0.3, 1.5, 2.7], [1, 3.6, 2.7], label="stem test")
  14. bottom_ax.legend()
  15. plt.show()

图例示例3

现在我们将展示带有多个关键图例的图例条目。

  1. fig, (ax1, ax2) = plt.subplots(2, 1, constrained_layout=True)
  2. # First plot: two legend keys for a single entry
  3. p1 = ax1.scatter([1], [5], c='r', marker='s', s=100)
  4. p2 = ax1.scatter([3], [2], c='b', marker='o', s=100)
  5. # `plot` returns a list, but we want the handle - thus the comma on the left
  6. p3, = ax1.plot([1, 5], [4, 4], 'm-d')
  7. # Assign two of the handles to the same legend entry by putting them in a tuple
  8. # and using a generic handler map (which would be used for any additional
  9. # tuples of handles like (p1, p3)).
  10. l = ax1.legend([(p1, p3), p2], ['two keys', 'one key'], scatterpoints=1,
  11. numpoints=1, handler_map={tuple: HandlerTuple(ndivide=None)})
  12. # Second plot: plot two bar charts on top of each other and change the padding
  13. # between the legend keys
  14. x_left = [1, 2, 3]
  15. y_pos = [1, 3, 2]
  16. y_neg = [2, 1, 4]
  17. rneg = ax2.bar(x_left, y_neg, width=0.5, color='w', hatch='///', label='-1')
  18. rpos = ax2.bar(x_left, y_pos, width=0.5, color='k', label='+1')
  19. # Treat each legend entry differently by using specific `HandlerTuple`s
  20. l = ax2.legend([(rpos, rneg), (rneg, rpos)], ['pad!=0', 'pad=0'],
  21. handler_map={(rpos, rneg): HandlerTuple(ndivide=None),
  22. (rneg, rpos): HandlerTuple(ndivide=None, pad=0.)})
  23. plt.show()

图例示例4

最后,还可以编写定义如何对图例进行样式化的自定义对象。

  1. class HandlerDashedLines(HandlerLineCollection):
  2. """
  3. Custom Handler for LineCollection instances.
  4. """
  5. def create_artists(self, legend, orig_handle,
  6. xdescent, ydescent, width, height, fontsize, trans):
  7. # figure out how many lines there are
  8. numlines = len(orig_handle.get_segments())
  9. xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent,
  10. width, height, fontsize)
  11. leglines = []
  12. # divide the vertical space where the lines will go
  13. # into equal parts based on the number of lines
  14. ydata = ((height) / (numlines + 1)) * np.ones(xdata.shape, float)
  15. # for each line, create the line at the proper location
  16. # and set the dash pattern
  17. for i in range(numlines):
  18. legline = Line2D(xdata, ydata * (numlines - i) - ydescent)
  19. self.update_prop(legline, orig_handle, legend)
  20. # set color, dash pattern, and linewidth to that
  21. # of the lines in linecollection
  22. try:
  23. color = orig_handle.get_colors()[i]
  24. except IndexError:
  25. color = orig_handle.get_colors()[0]
  26. try:
  27. dashes = orig_handle.get_dashes()[i]
  28. except IndexError:
  29. dashes = orig_handle.get_dashes()[0]
  30. try:
  31. lw = orig_handle.get_linewidths()[i]
  32. except IndexError:
  33. lw = orig_handle.get_linewidths()[0]
  34. if dashes[0] is not None:
  35. legline.set_dashes(dashes[1])
  36. legline.set_color(color)
  37. legline.set_transform(trans)
  38. legline.set_linewidth(lw)
  39. leglines.append(legline)
  40. return leglines
  41. x = np.linspace(0, 5, 100)
  42. fig, ax = plt.subplots()
  43. colors = plt.rcParams['axes.prop_cycle'].by_key()['color'][:5]
  44. styles = ['solid', 'dashed', 'dashed', 'dashed', 'solid']
  45. lines = []
  46. for i, color, style in zip(range(5), colors, styles):
  47. ax.plot(x, np.sin(x) - .1 * i, c=color, ls=style)
  48. # make proxy artists
  49. # make list of one line -- doesn't matter what the coordinates are
  50. line = [[(0, 0)]]
  51. # set up the proxy artist
  52. lc = mcol.LineCollection(5 * line, linestyles=styles, colors=colors)
  53. # create the legend
  54. ax.legend([lc], ['multi-line'], handler_map={type(lc): HandlerDashedLines()},
  55. handlelength=2.5, handleheight=3)
  56. plt.show()

图例示例5

下载这个示例