Home > database >  create legend for markercolor and size
create legend for markercolor and size

Time:09-23

I've created the following figure:

enter image description here

With following code:

matplotlib.rcParams.update({'font.size': 10})

fig = plt.figure(figsize=(16, 9), dpi=300, facecolor='white')
ax = plt.subplot(111, projection=ccrs.PlateCarree())
ax.set_extent(extent)

# cartopy layers
country_10m = cartopy.feature.NaturalEarthFeature('cultural', 'admin_0_countries', '10m')
ax.add_feature(country_10m, edgecolor='w', linewidth=0.75, facecolor='#EEEFEE', label='country border')
ax.coastlines(resolution='10m', color='#EEEFEE', linewidth=0.75)
ax.imshow(np.tile(np.array([[[191, 210, 217]]], dtype=np.uint8), [2, 2, 1]), origin='lower', transform=cartopy.crs.PlateCarree(), extent=extent)

ax.scatter(gdf_ldb.x, gdf_ldb.y, c= gdf_ldb.Color, s= gdf_ldb.Markersize, zorder=30) 
# ax.scatter(gdf_ports_filt.longitude, gdf_ports_filt.latitude, s= 10, color= 'k', zorder= 30)

ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='-')
ax.text(-0.08, 0.5, 'latitude [°]', va='bottom', ha='center',rotation='vertical', rotation_mode='anchor',transform=ax.transAxes);
ax.text(0.5, -0.09, 'longitude [°]', va='bottom', ha='center', rotation='horizontal', rotation_mode='anchor', transform=ax.transAxes);

How do I create a legend for the markersize as well for the color, so like this:

enter image description here

With x, x1, and x2 representing the values of the markersizes.

gdf_ldb looks like:

    x   y   Type    Color   Markersize  geometry
prograding_feature_polygon_29   12.857701   56.648035   Updrift grey    3.0 POINT (12.85770 56.64804)
prograding_feature_polygon_57   17.781445   54.808079   Updrift grey    3.0 POINT (17.78144 54.80808)
prograding_feature_polygon_58   17.438390   54.754518   Updrift grey    3.0 POINT (17.43839 54.75452)
prograding_feature_polygon_63   4.708077    52.880322   Updrift grey    3.0 POINT (4.70808 52.88032)
prograding_feature_polygon_72   3.953364    51.842299   Updrift grey    3.0 POINT (3.95336 51.84230)
... ... ... ... ... ... ...
retreating_feature_polygon_2018 -10.148432  53.415224   Double Updrift  grey    3.0 POINT (-10.14843 53.41522)
retreating_feature_polygon_2019 -9.954510   54.197329   Double Updrift  grey    3.0 POINT (-9.95451 54.19733)
retreating_feature_polygon_2119 15.095564   37.389535   Double Updrift  grey    3.0 POINT (15.09556 37.38953)
retreating_feature_polygon_2120 14.317893   37.025026   Double Updrift  grey    3.0 POINT (14.31789 37.02503)
retreating_feature_polygon_2121 13.952111   37.101009   Updrift grey    3.0 POINT (13.95211 37.10101)



Thanks in advance,

Dante

CodePudding user response:

The key is to capture the artist (PathCollection in this case) returned by the scatter command. That has a method to retrieve the legend items manually, and it has keywords to distinguish between size and color (default). The num keyword can be used to reduce the amount of items returned, which is useful in the case of a (semi)continuous property as the size can be.

The example below plots two separate legends for both properties. You can also combine the handles and labels of both and plot them in a single legend if needed.

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import cartopy.crs as ccrs
import cartopy
import numpy as np

lons = np.random.randint(-170, 170, 100)
lats = np.random.randint(-80, 80, 100)
sizes = np.random.rand(100) * 100   5
colors = np.random.randint(0, 3, 100)

fig, ax = plt.subplots(
    figsize=(8,4), dpi=86, facecolor='w', 
    subplot_kw=dict(projection=ccrs.PlateCarree()),
)
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)

ax.add_feature(cartopy.feature.LAND, ec='none', fc='#EEEFEE', label='country border')
ax.add_feature(cartopy.feature.BORDERS, ec='w', fc='k', lw=0.75, label='country border')
ax.coastlines(resolution='10m', color='#EEEFEE', lw=0.75)

m = ax.scatter(lons, lats, s=sizes, c=colors, zorder=5, label="points")

l1 = ax.legend(
    *m.legend_elements(prop="colors", num="auto"), title="Colors", framealpha=1, 
    loc="upper right", bbox_to_anchor=(0.88, 0.8, 0.12, 0.2), mode="expand",
)
ax.add_artist(l1) # prevent overwriting with second legend

l2 = ax.legend(
    *m.legend_elements(prop="sizes", num=5), title="Sizes", framealpha=1,
    loc="upper right", bbox_to_anchor=(0.88, 0.55, 0.12, 0.2), mode="expand",
)

enter image description here

The documentation about this shows some variations on this:
single_legend

  • Related