Matplotlib中如何在子图中添加图例:全面指南

Matplotlib中如何在子图中添加图例:全面指南

参考:Matplotlib legend in subplot

Matplotlib是Python中最流行的数据可视化库之一,它提供了强大的绘图功能。在数据可视化中,图例(legend)是一个非常重要的元素,它可以帮助读者理解图表中不同数据系列的含义。当我们在使用子图(subplot)时,如何正确地添加和调整图例就变得尤为重要。本文将全面介绍如何在Matplotlib的子图中添加和自定义图例,包括基本用法、位置调整、样式设置等多个方面。

1. 基本图例添加

在Matplotlib中,我们可以使用legend()方法来添加图例。对于子图,我们通常在每个子图上单独添加图例。以下是一个基本的示例:

import matplotlib.pyplot as plt
import numpy as np

# 创建数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 创建图形和子图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

# 在第一个子图中绘制数据并添加图例
ax1.plot(x, y1, label='Sin(x)')
ax1.plot(x, y2, label='Cos(x)')
ax1.legend()
ax1.set_title('Subplot 1 - how2matplotlib.com')

# 在第二个子图中绘制数据并添加图例
ax2.plot(x, y1**2, label='Sin^2(x)')
ax2.plot(x, y2**2, label='Cos^2(x)')
ax2.legend()
ax2.set_title('Subplot 2 - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们创建了两个子图,每个子图都包含两条线。我们使用label参数为每条线指定标签,然后调用legend()方法来显示图例。tight_layout()函数用于自动调整子图之间的间距。

2. 图例位置调整

默认情况下,Matplotlib会自动选择一个合适的位置放置图例。但有时我们可能需要手动指定图例的位置。我们可以通过legend()方法的loc参数来实现这一点。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

ax1.plot(x, y1, label='Sin(x)')
ax1.plot(x, y2, label='Cos(x)')
ax1.legend(loc='upper right')
ax1.set_title('Legend at upper right - how2matplotlib.com')

ax2.plot(x, y1, label='Sin(x)')
ax2.plot(x, y2, label='Cos(x)')
ax2.legend(loc='lower left')
ax2.set_title('Legend at lower left - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们在第一个子图中将图例放置在右上角('upper right'),在第二个子图中将图例放置在左下角('lower left')。Matplotlib提供了多个预定义的位置,如'upper left', 'center', 'best'等。

3. 使用坐标指定图例位置

除了使用预定义的位置,我们还可以使用坐标来精确指定图例的位置。这可以通过bbox_to_anchor参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

ax1.plot(x, y1, label='Sin(x)')
ax1.plot(x, y2, label='Cos(x)')
ax1.legend(bbox_to_anchor=(0.5, 1.05), loc='lower center', ncol=2)
ax1.set_title('Legend above plot - how2matplotlib.com')

ax2.plot(x, y1, label='Sin(x)')
ax2.plot(x, y2, label='Cos(x)')
ax2.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
ax2.set_title('Legend to the right - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们在第一个子图中将图例放置在图表上方,在第二个子图中将图例放置在图表右侧。bbox_to_anchor参数接受一个元组,表示图例锚点的坐标。loc参数指定图例相对于锚点的位置。

4. 调整图例样式

我们可以通过多种方式来自定义图例的样式,包括改变字体大小、颜色、边框等。以下是一个示例:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

ax1.plot(x, y1, label='Sin(x)')
ax1.plot(x, y2, label='Cos(x)')
ax1.legend(fontsize=12, frameon=False, shadow=True)
ax1.set_title('Custom legend style 1 - how2matplotlib.com')

ax2.plot(x, y1, label='Sin(x)')
ax2.plot(x, y2, label='Cos(x)')
ax2.legend(fancybox=True, framealpha=0.5, edgecolor='red')
ax2.set_title('Custom legend style 2 - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们展示了两种不同的图例样式。第一个子图中,我们增加了字体大小,移除了边框,并添加了阴影。第二个子图中,我们使用了圆角边框,设置了半透明的背景,并将边框颜色设置为红色。

5. 多列图例

当图例项目较多时,我们可能希望将图例排列成多列。这可以通过ncol参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

fig, ax = plt.subplots(figsize=(8, 6))

for i in range(5):
    ax.plot(x, np.sin(x + i), label=f'Sin(x + {i})')

ax.legend(ncol=3, loc='upper center', bbox_to_anchor=(0.5, 1.15))
ax.set_title('Multi-column legend - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们绘制了5条正弦曲线,并将它们的图例排列成3列,放置在图表上方。

6. 图例中的标记和线条

有时我们可能只想在图例中显示标记或线条,而不是两者都显示。我们可以通过设置markerfirst参数来控制标记和线条的顺序,或者使用handler_map来完全自定义图例项的外观:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))

ax1.plot(x, y1, 'o-', label='Sin(x)')
ax1.plot(x, y2, 's-', label='Cos(x)')
ax1.legend(markerfirst=False)
ax1.set_title('Legend with markers last - how2matplotlib.com')

from matplotlib.legend_handler import HandlerLine2D

line1, = ax2.plot(x, y1, 'o-', label='Sin(x)')
line2, = ax2.plot(x, y2, 's-', label='Cos(x)')
ax2.legend(handler_map={line1: HandlerLine2D(numpoints=1), line2: HandlerLine2D(numpoints=1)})
ax2.set_title('Legend with single point - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,第一个子图展示了如何将标记放在线条后面。第二个子图展示了如何在图例中只显示一个点,而不是默认的两个点。

7. 图例中的颜色块

有时我们可能想在图例中显示颜色块而不是线条或标记。这在绘制热图或其他类型的填充图时特别有用:

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(8, 6))

data = np.random.rand(10, 10)
im = ax.imshow(data, cmap='viridis')

# 创建颜色块
import matplotlib.patches as mpatches
red_patch = mpatches.Patch(color='red', label='Red')
blue_patch = mpatches.Patch(color='blue', label='Blue')
green_patch = mpatches.Patch(color='green', label='Green')

ax.legend(handles=[red_patch, blue_patch, green_patch])
ax.set_title('Legend with color patches - how2matplotlib.com')

plt.colorbar(im)
plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们创建了一个热图,并在图例中添加了三个颜色块。虽然这些颜色块并不对应热图中的实际数据,但这个技巧在需要解释不同颜色含义的场景中非常有用。

8. 自定义图例标签

有时我们可能需要在图例中显示更复杂的标签,比如包含数学公式或特殊格式的文本。Matplotlib支持在标签中使用LaTeX语法:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label=r'\sin(x)')
ax.plot(x, y2, label=r'\cos(x)')
ax.legend(fontsize=14)
ax.set_title('Legend with LaTeX labels - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们使用LaTeX语法来创建数学公式作为图例标签。注意标签字符串前的r,它表示这是一个原始字符串,防止反斜杠被解释为转义字符。

9. 图例中的图像

在某些情况下,我们可能想在图例中包含小图像。这可以通过自定义图例处理器来实现:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.legend_handler import HandlerBase
from matplotlib.patches import Rectangle

class ImageHandler(HandlerBase):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        return [Rectangle((xdescent, ydescent), width, height, fc=orig_handle)]

fig, ax = plt.subplots(figsize=(8, 6))

x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), label='Sin(x)')
ax.plot(x, np.cos(x), label='Cos(x)')

red_square = plt.Rectangle((0, 0), 1, 1, fc="r")
blue_square = plt.Rectangle((0, 0), 1, 1, fc="b")

ax.legend([red_square, blue_square], ['Red', 'Blue'], 
          handler_map={Rectangle: ImageHandler()})
ax.set_title('Legend with custom handlers - how2matplotlib.com')

plt.tight_layout()
plt.show()

在这个例子中,我们创建了一个自定义的ImageHandler类来处理Rectangle对象。这允许我们在图例中显示颜色块,但这种方法也可以扩展到显示实际的图像。

10. 多图例

有时我们可能需要在一个子图中显示多个图例。这可以通过多次调用legend()方法并使用add_artist()方法来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = x**2

fig, ax = plt.subplots(figsize=(8, 6))

line1, = ax.plot(x, y1, 'r-', label='Sin(x)')
line2, = ax.plot(x, y2, 'b-', label='Cos(x)')
line3, = ax.plot(x, y3, 'g-', label='Tan(x)')
line4, = ax.plot(x, y4, 'y-', label='x^2')

# 创建第一个图例
legend1 = ax.legend(handles=[line1, line2], loc='upper left')
ax.add_artist(legend1)

# 创建第二个图例
ax.legend(handles=[line3, line4], loc='upper right')

ax.set_title('Multiple legends - how2matplotlib.com')
plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们在一个子图中创建了两个独立的图例,一个位于左上角,另一个位于右上角。

11. ## 11. 图例中的透明度

在某些情况下,我们可能希望图例中的元素具有与实际绘图元素相同的透明度。这可以通过设置图例的alpha参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label='Sin(x)', alpha=0.5)
ax.plot(x, y2, label='Cos(x)', alpha=0.5)

ax.legend(framealpha=0.5)
ax.set_title('Legend with transparency - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们将线条的透明度设置为0.5,并将图例的背景透明度也设置为0.5。这样可以确保图例的视觉效果与实际绘图元素保持一致。

12. 图例中的标记大小

有时,我们可能需要调整图例中标记的大小。这可以通过markerscale参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, 'o-', label='Sin(x)', markersize=10)
ax.plot(x, y2, 's-', label='Cos(x)', markersize=10)

ax.legend(markerscale=0.5)
ax.set_title('Legend with scaled markers - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们将图例中的标记大小设置为实际绘图中标记大小的一半。这在处理大标记时特别有用,可以防止图例变得过大。

13. 图例框的样式

Matplotlib允许我们自定义图例框的样式,包括边框颜色、填充颜色、阴影等:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label='Sin(x)')
ax.plot(x, y2, label='Cos(x)')

ax.legend(facecolor='lightgray', edgecolor='black', shadow=True)
ax.set_title('Legend with custom box style - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们将图例的背景色设置为浅灰色,边框设置为黑色,并添加了阴影效果。这可以使图例在视觉上更加突出。

14. 图例中的行间距

当图例中有多个项目时,我们可能需要调整项目之间的间距。这可以通过labelspacing参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

fig, ax = plt.subplots(figsize=(8, 6))

for i in range(5):
    ax.plot(x, np.sin(x + i), label=f'Sin(x + {i})')

ax.legend(labelspacing=1.5)
ax.set_title('Legend with increased label spacing - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们增加了图例项目之间的间距,使得图例更加清晰易读。

15. 图例中的列间距

当使用多列图例时,我们可能需要调整列之间的间距。这可以通过columnspacing参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

fig, ax = plt.subplots(figsize=(10, 6))

for i in range(6):
    ax.plot(x, np.sin(x + i), label=f'Sin(x + {i})')

ax.legend(ncol=3, columnspacing=1.5)
ax.set_title('Legend with increased column spacing - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们创建了一个三列的图例,并增加了列之间的间距。

16. 图例中的句柄长度

图例中的句柄(即线条或标记的示例)的长度也是可以调整的。这可以通过handlelength参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label='Sin(x)')
ax.plot(x, y2, label='Cos(x)')

ax.legend(handlelength=5)
ax.set_title('Legend with longer handles - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们增加了图例中句柄的长度,使得线条的示例更加明显。

17. 图例中的文本对齐

我们可以调整图例中文本的对齐方式。这可以通过handletextpad参数来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label='Sin(x)')
ax.plot(x, y2, label='Cos(x)')

ax.legend(handletextpad=0.5)
ax.set_title('Legend with adjusted text alignment - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们减小了句柄和文本之间的间距,使得图例更加紧凑。

18. 自定义图例顺序

有时我们可能想要自定义图例中项目的顺序。这可以通过手动指定图例项来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)

fig, ax = plt.subplots(figsize=(8, 6))

line1, = ax.plot(x, y1, label='Sin(x)')
line2, = ax.plot(x, y2, label='Cos(x)')
line3, = ax.plot(x, y3, label='Tan(x)')

ax.legend([line3, line1, line2])  # 自定义顺序
ax.set_title('Legend with custom order - how2matplotlib.com')

plt.tight_layout()
plt.show()

在这个例子中,我们改变了图例中项目的顺序,使得Tan(x)出现在最前面。

19. 图例中的换行

当图例标签较长时,我们可能需要在标签中添加换行。这可以通过在标签字符串中使用\n来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

ax.plot(x, y1, label='Sine function\n(oscillating)')
ax.plot(x, y2, label='Cosine function\n(phase-shifted sine)')

ax.legend()
ax.set_title('Legend with line breaks - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们在图例标签中添加了换行,使得每个标签占用两行。

20. 动态更新图例

在某些情况下,我们可能需要在绘图过程中动态更新图例。这可以通过重新调用legend()方法来实现:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots(figsize=(8, 6))

line1, = ax.plot(x, y1, label='Sin(x)')
line2, = ax.plot(x, y2, label='Cos(x)')

legend = ax.legend()

# 更新图例
line1.set_label('Updated Sin(x)')
line2.set_label('Updated Cos(x)')
ax.legend()

ax.set_title('Legend with updated labels - how2matplotlib.com')

plt.tight_layout()
plt.show()

Output:

Matplotlib中如何在子图中添加图例:全面指南

在这个例子中,我们首先创建了一个图例,然后更新了线条的标签,并重新调用legend()方法来更新图例。

总结起来,Matplotlib提供了丰富的选项来自定义子图中的图例。通过调整位置、样式、内容等各个方面,我们可以创建出清晰、美观、信息丰富的图例,从而提高数据可视化的质量。在实际应用中,根据具体需求和数据特性,灵活运用这些技巧可以大大提升图表的可读性和专业性。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程