
本文详细介绍了在 matplotlib 中如何为地图生成包含多种元素的图例,特别是如何将代表区域的色块图例与代表特定点的自定义符号标记图例有效地整合到同一个图例框中。通过使用 `matplotlib.lines.Line2D` 代替传统的 `matplotlib.patches.Patch`,可以确保图例中的标记准确无误地呈现为用户指定的符号,从而提升图例的清晰度和信息表达能力。
在数据可视化中,尤其是在地图应用中,我们经常需要在一个图例中展示多种类型的信息。例如,地图上的区域可能通过颜色来表示不同的类别(如犯罪率等级),而特定的地理点(如资产位置)则可能通过自定义的符号标记来突出显示。将这两种不同类型的视觉元素(色块和符号)清晰地呈现在同一个图例中,是提升地图可读性的关键。
问题分析与原始实现
最初的实现尝试将表示区域风险等级的色块图例与表示资产位置的符号标记图例合并。对于区域风险等级,使用 matplotlib.patches.Patch 来创建颜色方块作为图例项是标准且有效的方法。然而,当尝试为资产位置创建一个带有自定义标记(例如 ‘x’)的图例时,如果仍然使用 Patch,则会出现问题。
考虑以下原始代码片段:
import matplotlib.pyplot as plt from matplotlib.patches import Patch import matplotlib.lines as mlines # 导入但未用于原始图例 # 假设 color_list 已定义,用于生成区域色块图例 patches = [] for category, color in color_list.items(): patch = Patch(color=color, label=category) patches.append(patch) # 假设 sao 和 asset 是 GeoDataFrame,ax 是 Matplotlib 轴对象 # sao.plot(...) # 绘制区域 # asset.plot(color='black', markersize = 110, marker= "$x$", ax=ax, label = "assets") # 原始的图例创建方式,问题在于资产图例项 plt.legend(handles=patches + [Patch(color='black', label="assets")], loc='lower right', title = 'Crime Rate Level for Districts') plt.show()
这段代码的问题在于,Patch(color=’black’, label=”assets”) 会在图例中生成一个黑色的方块,而不是一个黑色的 ‘x’ 标记。这与地图上实际绘制的资产标记 ‘$x$’ 不符,导致图例信息不准确,降低了图例的有效性。
解决方案:利用 matplotlib.lines.Line2D
为了在图例中准确地表示自定义符号标记,我们需要使用 matplotlib.lines.Line2D 对象。Line2D 不仅可以用于表示线条,还可以通过设置 linestyle=” 和 marker 参数来专门表示没有线条的标记。
通过 Line2D,我们可以精确控制图例中标记的样式,包括其形状、颜色和大小。
from matplotlib.lines import Line2D # ... (假设 patches 已经按照上述方式创建) ... # 为资产点创建 Line2D 图例项 asset_legend_handle = Line2D( [], [], # 空列表表示没有实际数据点,仅用于图例 marker='x', # 指定标记样式为 'x' linestyle='', # 不显示线条 color='black', # 标记颜色 markersize=10, # 标记大小,可根据图中实际标记大小调整 label="Assets" # 图例标签 ) # 整合所有图例项:色块图例和 Line2D 标记图例 plt.legend( handles=patches + [asset_legend_handle], loc='lower right', title='Risk Areas - São Paulo, Brazil' )
通过这种方式,图例中“Assets”对应的条目将正确显示为一个黑色的 ‘x’ 标记,与地图上的实际标记保持一致。
完整示例代码
为了更清晰地展示这一解决方案,下面是一个包含模拟数据和完整绘图逻辑的示例:
import matplotlib.pyplot as plt from matplotlib.patches import Patch from matplotlib.lines import Line2D import pandas as pd import geopandas as gpd from shapely.geometry import Polygon, Point # --- 模拟数据 --- # 模拟犯罪率区域及颜色 color_list = { 'Low Risk': 'green', 'Medium Risk': 'orange', 'High Risk': 'red' } # 模拟区域几何数据 (简化为矩形) data = { 'district': ['A', 'B', 'C'], 'geometry': [ Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]), Polygon([(1, 1), (1, 2), (2, 2), (2, 1), (1, 1)]), Polygon([(2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]) ], 'Colors': ['green', 'orange', 'red'] # 对应color_list } sao = gpd.GeoDataFrame(data, geometry='geometry') # 模拟资产点 asset_data = {'geometry': [Point(0.5, 0.5), Point(1.5, 1.5)]} asset = gpd.GeoDataFrame(asset_data, geometry='geometry') # --- 绘图部分 --- fig, ax = plt.subplots(figsize=(10, 8)) # 绘制区域 sao.plot(color=sao["Colors"], ax=ax, edgecolor='black', linewidth=0.5) # 绘制资产点 asset.plot(color='black', markersize=200, marker="$x$", ax=ax, label="assets") # 创建区域风险等级的图例项 (Patch) patches = [] for category, color in color_list.items(): patch = Patch(color=color, label=category) patches.append(patch) # --- 解决方案:使用 Line2D 创建资产点的图例项 --- asset_legend_handle = Line2D( [], [], marker='x', # 使用 'x' 标记 linestyle='', # 不显示线条 color='black', # 标记颜色 markersize=10, # 标记大小 (可以调整以匹配图中实际大小) label="Assets" # 图例标签 ) # 整合所有图例项 plt.legend( handles=patches + [asset_legend_handle], loc='lower right', title='Risk Areas - São Paulo, Brazil' ) # 设置标题和移除坐标轴 ax.set_title('Risk Areas - São Paulo, Brazil', fontweight='bold') ax.axis('off') plt.show()
Line2D 关键参数解析
在创建 Line2D 对象作为图例项时,以下参数至关重要:
- []:前两个空列表表示该 Line2D 对象不关联实际的 x 和 y 数据点。它仅作为图例的视觉占位符。
- marker:指定要显示的标记样式,例如 ‘o’ (圆圈), ‘s’ (方块), ‘^’ (三角形), ‘$x$’ (文本 ‘x’) 等。
- linestyle:控制线条样式。设置为 ” 或 ‘None’ 表示不绘制线条,只显示标记。
- color:标记的颜色。
- markersize:标记在图例中的显示大小。这个值通常需要根据地图上实际绘制的标记大小进行调整,以保持视觉上的一致性。
- label:图例中显示的文本标签。
注意事项与最佳实践
- 标记大小一致性:图例中的 markersize 应尽可能与地图上实际绘制的标记大小相匹配。这有助于读者快速准确地理解图例与地图内容之间的对应关系。
- 选择合适的图例项类型:
- 对于表示颜色区域、填充色块或条形的图例,matplotlib.patches.Patch 是首选。
- 对于表示点、线、散点图中的标记或自定义符号的图例,matplotlib.lines.Line2D 是更准确的选择。
- 图例位置与标题:合理设置 loc 参数(如 ‘lower right’、’upper left’ 等)以避免图例遮挡重要地图内容。使用 title 参数为图例提供清晰的整体说明。
- 自定义图例处理器:对于更复杂的图例需求,例如需要自定义图例项的绘制方式,可以探索使用 matplotlib.legend.LegendHandler 和 handler_map。这允许您为特定类型的艺术家(Artist)或自定义对象定义如何生成其图例条目。
总结
在 Matplotlib 中创建包含多种元素的地图图例,特别是整合色块和自定义符号标记时,关键在于选择正确的图例项类型。通过将表示区域的色块与使用 matplotlib.lines.Line2D 创建的自定义符号标记相结合,我们可以确保图例的准确性和专业性。Line2D 提供了灵活的参数来精确控制标记的样式,从而有效提升了地图的可读性和信息传达效率。掌握这一技巧,将使您在 Matplotlib 中创建更具表现力的可视化作品。


