Home > Enterprise >  Make two markers share the same labels and simultaneously keep the black edge of patch in legend usi
Make two markers share the same labels and simultaneously keep the black edge of patch in legend usi

Time:03-13

How should I modify my following code to make two markers share the same labels and simultaneously keep the black edge of patch in legend? Here are code (I have plotted the bars twice to decouple the edge color and hatch color) and plotted picture. I want to make the markers as shown in the second picture.

import matplotlib
matplotlib.rcParams['pdf.fonttype'] = 42
matplotlib.rcParams['ps.fonttype'] = 42
import matplotlib.pyplot as plt

x_lable = ['3', '4', '5', '6', '7']

width = 0.3

Data1 = [96, 99, 100, 100, 100]
Data2 = [94, 96, 95, 96, 95]
Data3 = [48, 43, 42, 42, 37]

data_3 = [2228, 2621, 3165, 3761, 3763]
data_4 = [3895, 5670, 7354, 8999, 10731]
data_5 = [4355, 6373, 8279, 10105, 12018]

xcoordinate = [1, 3, 5, 7, 9]
xcoordinate_1 = [xcoordinate[0]   0 * width, xcoordinate[1]   0 * width, xcoordinate[2]   0 * width, xcoordinate[3]   0 * width, xcoordinate[4]   0 * width]
xcoordinate_2 = [xcoordinate[0]   1 * width, xcoordinate[1]   1 * width, xcoordinate[2]   1 * width, xcoordinate[3]   1 * width, xcoordinate[4]   1 * width]
xcoordinate_3 = [xcoordinate[0]   2 * width, xcoordinate[1]   2 * width, xcoordinate[2]   2 * width, xcoordinate[3]   2 * width, xcoordinate[4]   2 * width]
xcoordinate_4 = [xcoordinate[0]   3 * width, xcoordinate[1]   3 * width, xcoordinate[2]   3 * width, xcoordinate[3]   3 * width, xcoordinate[4]   3 * width]
xcoordinate_5 = [xcoordinate[0]   4 * width, xcoordinate[1]   4 * width, xcoordinate[2]   4 * width, xcoordinate[3]   4 * width, xcoordinate[4]   4 * width]

fig = plt.figure()

# plot ax1
ax1 = fig.add_subplot(111)

ax1.bar(xcoordinate_3, data_3, width=width, label='GGG', color='none', edgecolor='orange', hatch='\\\\\\')
ax1.bar(xcoordinate_4, data_4, width=width, label='SSS', color='none', edgecolor='blue', hatch='---')
ax1.bar(xcoordinate_5, data_5, width=width, label='KKK', color='none', edgecolor='orangered', hatch='///')

ax1.set_ylabel('BBB')
ax1.set_xlabel('AAA')

ax1.bar(xcoordinate_3, data_3, width=width, label='GGG', color='none', edgecolor='black')
ax1.bar(xcoordinate_4, data_4, width=width, label='SSS', color='none', edgecolor='black')
ax1.bar(xcoordinate_5, data_5, width=width, label='KKK', color='none', edgecolor='black')

handles1, labels1 = ax1.get_legend_handles_labels()
order = [0, 1, 2]
plt.legend([handles1[idx]   handles1[idx 3] for idx in order], [labels1[idx] for idx in order], loc=(2.5/10, 1.08), frameon=True, ncol=3, shadow=False, framealpha=1, labelspacing=1.05).get_frame().set_edgecolor('black')

# plot ax2
ax2 = ax1.twinx()

ax2.plot([i   3 * width for i in xcoordinate], Data3, label='GGG', color='orange', linestyle='-', marker='p')
ax2.plot([i   3 * width for i in xcoordinate], Data2, label='SSS', color='orangered', linestyle='-', marker='s')
ax2.plot([i   3 * width for i in xcoordinate], Data1, label='KKK', color='limegreen', linestyle='-', marker='^')

ax2.set_ylabel('CCC')
plt.xticks([i   3 * width for i in xcoordinate], x_lable)

handles2, labels2 = ax2.get_legend_handles_labels()
order = [0, 1, 2]
plt.legend([handles2[idx] for idx in order], [labels2[idx] for idx in order],  loc=(2.5/10, 1.005),  frameon=True, ncol=3, shadow=False, framealpha=1, labelspacing=1.05).get_frame().set_edgecolor('black')

plt.show()

Plotted picture:

fig1

What I want:

fig2

I want to keep the black edges of patches when two makers share the same label.

CodePudding user response:

The third example in the official guide is what you want. To combine each handler, set them up in tuple form. If you don't want each handler to be stacked, you can add a configuration.

from matplotlib.legend_handler import HandlerLineCollection, HandlerTuple

#plt.legend([handles1[idx]   handles1[ 3] for idx in order], [labels1[idx] for idx in order], loc=(2.5/10, 1.08), frameon=True, ncol=3, shadow=False, framealpha=1, labelspacing=1.05).get_frame().set_edgecolor('black')

plt.legend([(handles1[idx],handles2[idx]) for idx in order], [labels2[idx] for idx in order],  loc=(2.5/10, 1.005),  frameon=True, ncol=3, shadow=False, framealpha=1, labelspacing=1.05,handler_map={tuple: HandlerTuple(ndivide=None)}).get_frame().set_edgecolor('black')

enter image description here

CodePudding user response:

Seemingly, we cannot simply group handles arbitrarily using the enter image description here

I also increased the handle length with ...surprise... handlelength=5 because otherwise, we would not see much of the hatch pattern.

  • Related