matplotlib 如何创建自定义箭头形图例密钥

z9zf31ra  于 2023-05-23  发布在  其他
关注(0)|答案(1)|浏览(118)

我正在使用Matplotlib创建一个图。我希望图例键(图例中描述性文本旁边的形状)是类似于图中的箭头。我已经能够得到一个输出,这是接近我想要的,你可以看到在下面的图片。传说中有箭,但它们又长又窄。
The current iteration of my plot. The legend key arrows are present but tiny.
我用来创建图的代码如下:

# Define custom legend handler
class ArrowHandler(HandlerBase):
    def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans):
        arrow = FancyArrowPatch((0, 5), (40, 5), arrowstyle='->', color=orig_handle.get_edgecolor(), mutation_aspect=20)
        return [arrow]

# Plot the river profile using Matplotlib
plt.figure(figsize=(11, 6))
plt.plot(creek_long_profile_dataframes['Foley Creek']['distance_upstream_km'],
         creek_long_profile_dataframes['Foley Creek']['elevation_m'],
         color='#368bb5', linewidth=2)

### Add sediment delivery points as colored arrows
delivery_data = creek_sed_delivery_dataframes["Foley Creek"]

# Get range of x and y values to be able to standardize the size of the arrows
x_min_max = creek_long_profile_dataframes['Foley Creek']['distance_upstream_km'].agg(['min', 'max'])
x_range = x_min_max[1] - x_min_max[0]
y_min_max = creek_long_profile_dataframes['Foley Creek']['elevation_m'].agg(['min', 'max'])
y_range = y_min_max[1] - y_min_max[0]

# Add arrows to the figure
for index, row in delivery_data.iterrows():
    x = row['distance_upstream_km']
    y = row['elevation_m']
    color = '#1b9e77' if row['mass_movement_type'] == 'Debris Flow' else '#7570b3'
    plt.arrow(x, y+(0.098*y_range), 0, -(0.088*y_range), width=0.006*x_range, head_width=0.015*x_range,
              head_length=0.029*y_range, color=color, length_includes_head=True)

### done adding sediment delivery arrows

# Set axis labels
plt.xlabel('Distance upstream (km)')
plt.ylabel('Elevation (m)')

# Set title
plt.title('Sediment Delivery Along Foley Creek')

# Add grid
plt.grid(which='major', axis='both')

# Define the legend elements
legend_elements = [
    FancyArrowPatch((0, 0), (0, 0), arrowstyle='->', color='#1b9e77', label='Debris Flow'),
    FancyArrowPatch((0, 0), (0, 0), arrowstyle='->', color='#7570b3', label='Debris Avalanche')
]

# Create the legend with custom handler
plt.legend(handles=legend_elements, handler_map={FancyArrowPatch: ArrowHandler()})

# Save figure
# plt.savefig('sed_delivery_figs/sed_delivery_foley.pdf', dpi=300, bbox_inches='tight')

# Show the plot
plt.show()

我首先尝试传递一个类似于下面代码的Arrow示例列表。

# Define the legend elements
legend_elements = [
    FancyArrowPatch((0, 0), (0.5, 0), arrowstyle='->', color='#1b9e77', label='Debris Flow'),
    FancyArrowPatch((0, 0), (0.5, 0), arrowstyle='->', color='#7570b3', label='Debris Avalanche')
]

# Add the legend
plt(handles=legend_elements, loc='center')

这导致图例键是矩形的(不是我希望的箭头),但颜色是正确的。
我蹒跚地一起创建一个自定义的图例处理程序的一些代码,但不幸的是,我很少了解他们如何工作,我应该如何定义它。任何帮助将不胜感激。
我已经看了一些相关的文章(herehere),但是我还没有能够在我的用例中实现他们的建议,因为我在Matplotlib的某些方面遇到了麻烦。
有谁知道我怎样才能把箭头的传说一样,我绘制的数字本身?有没有更简单的方法?

jq6vz3qz

jq6vz3qz1#

很好地提出了你的问题,并提供了相关的支持细节。
我不能说我明白这一切是如何运作的。但是我可以说使用FancyArrow(来自matplotlib.patches)而不是FancyArrowPatch对我来说是有效的。你能试试这样的吗?

import matplotlib.patches as mpatches
for creek in creek_long_profile_dataframes:
    print(creek)
    # Define custom legend handler
    class ArrowHandler(HandlerBase):
        def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans):
            arrow = mpatches.FancyArrow(0, 3, 25, 0, color=orig_handle.get_edgecolor(), width=2.5, length_includes_head=False)
            return [arrow]

希望你能在你的传说中得到清晰可辨的箭头形状的箭头。(我的想法来自https://matplotlib.org/stable/gallery/shapes_and_collections/arrow_guide.html

相关问题