I have a GeoDataFrame I want to plot. This works fine, however somehow I cannot easily plot its legend. I have tried a number of alternatives and checked solutions from googling and LLM, but I do not understand why this does not work.
Code:
import geopandas as gpd
from shapely.geometry import box, Polygon, LineString
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
bounding_box = [9.454, 80.4, 12, 80.88]
polygon = box(*bounding_box)
gdf = gpd.GeoDataFrame(geometry=[polygon])
plot_obj = gdf.plot(ax=ax, edgecolor='red', facecolor='none', linewidth=2, label="user bbox query")
# plt.legend() # does not work
# ax.legend(handles=[plot_obj], labels=["test"]) # does not work
ax.legend(handles=[plot_obj]) # does not work
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.show()
Result:
I get a warning:
<python-input-0>:16: UserWarning: Legend does not support handles for Axes instances.
A proxy artist may be used instead.
See: https://matplotlib.org/stable/users/explain/axes/legend_guide.html#controlling-the-legend-entries
ax.legend(handles=[plot_obj]) # does not wor
But somehow I am not able to take advantage of it to make things work (I tried several ways to plot the legend from "handles", see the different attempts, but none work).
I am certainly missing something - any pointer to how this can be done simply? :)
In addition to the previous answer, set the legend on free space:
import geopandas as gpd
from shapely.geometry import box
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
fig, ax = plt.subplots()
bounding_box = [9.454, 80.4, 12, 80.88]
polygon = box(*bounding_box)
gdf = gpd.GeoDataFrame(geometry=[polygon])
gdf.plot(ax=ax, edgecolor='red', facecolor='none', linewidth=2)
# Create legend handle
legend_handle = mpatches.Patch(facecolor='none', edgecolor='red', linewidth=2, label='user bbox query')
# Add legend positioned outside the plot area
ax.legend(handles=[legend_handle], bbox_to_anchor=(1.05, 1), loc='upper left')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.tight_layout() # Adjust layout to make room for the legend
plt.show()