user140259
user140259

Reputation: 480

Custom legend of several lines with two markers for the same text

I would like perform the type of legend shown in the figure enter image description here.

That figure I did with some tricks just to represent what I really want so it does not show well the color of the pink markers in the legend.

In the figure the circles represent the same parameter but for two different models; the same is true for the triangular and square markers. I want to place the two circular markers referring to the same parameter in the first line of the legend, and analogously for the two other markers on the lines below this one. Thank you.

Code:

import matplotlib.pyplot as plt

q1 = [100.0, 60.0, 200.0, 300.0]
NO1 = [0.35799999999999998, 0.33100000000000002, 0.22900000000000001,     0.17799999999999999]
No1 = [0.34599999999999997, 0.29899999999999999, 0.20699999999999999, 0.14999999999999999]
Nb1 = [0.46600000000000003, 0.45600000000000002, 0.27800000000000002, 0.24399999999999999]

q2 = [60.0, 100.0, 200.0, 300.0]
NO2 = [0.44700000000000001, 0.29199999999999998, 0.28299999999999997, 0.253]
No2 = [0.38900000000000001, 0.28499999999999998, 0.311, 0.251]
Nb2 = [0.44, 0.34899999999999998, 0.45900000000000002, 0.39400000000000002]

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

ax.plot(q1, NO1, marker = 'o', markerfacecolor = 'none', markeredgewidth = 1, color = 'gray', linestyle = '', markersize = 8, label = '$N$ in parameter a')
ax.plot(q2, NO2, marker = 'o', markerfacecolor = 'none', markeredgewidth = 1, color = 'palevioletred', linestyle = '', markersize = 8)#, label = '$N$ in parameter a')
ax.plot(q1, No1, marker = '^', markerfacecolor = 'none', markeredgewidth = 1, color = 'gray', linestyle = '', markersize = 8, label = '$N$ in parameter b')
ax.plot(q2, No2, marker = '^', markerfacecolor = 'none', markeredgewidth = 1, color = 'palevioletred', linestyle = '', markersize = 8)#, label = '$N$ in parameter b')  
ax.plot(q1, Nb1, marker = 's', markerfacecolor = 'none', markeredgewidth = 1, color = 'gray', linestyle = '', markersize = 8, label = '$N$ in parameter c') 
ax.plot(q2, Nb2, marker = 's', markerfacecolor = 'none', markeredgewidth = 1, color = 'palevioletred', linestyle = '', markersize = 8)#, label = '$N$ in parameter c')
#plt.legend(loc='upper right', bbox_to_anchor=(0.945, 1))
plt.xlabel('x')
plt.ylabel('$N$')
plt.xticks([60, 100, 200, 300])
plt.minorticks_on()
plt.tick_params(direction = 'in', bottom = True, top = True, left = True, right = True, which = 'major')    
plt.tick_params(direction = 'in', bottom = False, top = False, left = True, right = True, which = 'minor')  

Upvotes: 3

Views: 2970

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339112

You may use a HandlerTuple handler and provide tuples of the artists to show in each row as handles to the legend.

import matplotlib.pyplot as plt
import matplotlib.legend_handler

q1 = [100.0, 60.0, 200.0, 300.0]
NO1 = [0.358, 0.331, 0.229, 0.178]
No1 = [0.346, 0.299, 0.207, 0.15]
Nb1 = [0.466, 0.456, 0.278, 0.244]

q2 = [60.0, 100.0, 200.0, 300.0]
NO2 = [0.447, 0.292, 0.283, 0.253]
No2 = [0.389, 0.285, 0.311, 0.251]
Nb2 = [0.44, 0.349, 0.459, 0.394]

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

prop = dict(markerfacecolor = 'none', markeredgewidth = 1,
            linestyle = '', markersize = 8,)
l1, = ax.plot(q1, NO1, marker = 'o', color = 'gray', label = '$N$ in parameter a', **prop)
l2, = ax.plot(q2, NO2, marker = 'o', color = 'palevioletred', **prop)
l3, = ax.plot(q1, No1, marker = '^', color = 'gray', label = '$N$ in parameter b', **prop)
l4, = ax.plot(q2, No2, marker = '^', color = 'palevioletred', **prop)
l5, = ax.plot(q1, Nb1, marker = 's', color = 'gray', label = '$N$ in parameter c', **prop) 
l6, = ax.plot(q2, Nb2, marker = 's', color = 'palevioletred', **prop)


handles = [(l1,l2), (l3,l4), (l5,l6)]
_, labels = ax.get_legend_handles_labels()

ax.legend(handles = handles, labels=labels, loc='upper right', 
          handler_map = {tuple: matplotlib.legend_handler.HandlerTuple(None)})

plt.xlabel('x')
plt.ylabel('$N$')

plt.show()

enter image description here

Upvotes: 7

Related Questions