2

I'm trying to center the markers in the second row of my legend.

I already tried to follow the instructions of Centering matplotlib legend entries within incomplete/unfilled rows? but I didn't fit for my code and i don't understand why. Maybe because I have errorbars or i generated different axes? Here's an example of my code:

#EXAMPLE OF MY DATA

x = [0, 2, 5, 10, 15]
y1 = [1, 2, 4, 5, 2]
dev1 = [0.2, 0.3, 0.4, 0.6, 0.4]
y2 =[1, 2, 3, 4, 5]
dev2 = [0.01, 0.2, 0.3, 0.4, 0.5]
y3 =[2, 4, 0, 1, 5]
dev3 = [0.1, 0.2, 0.2, 0.4, 0.5]
y4 =[2, 2, 1, 1, 1]
dev4 = [0.1, 0.1, 0.1, 0, 0]
y5 =[2, 2, 1, 2, 2]
dev5 = [0, 0, 0.1, 0, 0]

#####

fig, ax = plt.subplots()
ax.errorbar(x, y1, yerr=dev1, marker="^", markersize=4, linestyle=" ", capsize=4, capthick=2, color="darkorange", label='line1')
ax.errorbar(x, y2, yerr=dev2, marker="s", markersize=4, linestyle=" ", capsize=4, capthick=2, color="green", label='line2')
ax.errorbar(x, y3, yerr=dev3, marker="v", markersize=4, linestyle=" ", capsize=4, capthick=2, color="blue", label='line3')
ax.errorbar(x, y4, yerr=dev4, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="brown", label='line4')
ax.errorbar(x, y5, yerr=dev5, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="yellow", label='line5')

handles1, labels1 = ax.get_legend_handles_labels()
handles1 = [h[0] for h in handles1]
nlines=6
ncols=3
handles1.insert(nlines//ncols, plt.plot([],[],color=(0,0,0,0))[0])
labels1.insert(nlines//ncols, " ") #--->I tried to insert this although it raises me an error (there are 6 handles and 5 labels)<----
ax.legend(handles=handles1, labels=labels1, ncol=ncols, framealpha=1)

This is what I have at the end.

enter image description here

The legend is not how expected. I would like something like:

enter image description here

Djova
  • 35
  • 3

1 Answers1

1

I have borrowed some of the information from the link you provided below, along with this answer. The reason for the second one is because you wanted to order the legend entries horizontally (by row) rather than by column. So, let me go through the steps...

  1. Once you have plotted the graph as per your code, I used the flip function to convert the legend to be ordered horizontally - basically labels 1 thru 3 on the first row and 4,5 on the second row.
  2. Post that, I created leg1 for the first row and leg2 for the second. Then, added the artist of leg2 to leg1 and we have the required plot.

Hope this is what you are looking for...

#EXAMPLE OF MY DATA
x = [0, 2, 5, 10, 15]
y1 = [1, 2, 4, 5, 2]
dev1 = [0.2, 0.3, 0.4, 0.6, 0.4]
y2 =[1, 2, 3, 4, 5]
dev2 = [0.01, 0.2, 0.3, 0.4, 0.5]
y3 =[2, 4, 0, 1, 5]
dev3 = [0.1, 0.2, 0.2, 0.4, 0.5]
y4 =[2, 2, 1, 1, 1]
dev4 = [0.1, 0.1, 0.1, 0, 0]
y5 =[2, 2, 1, 2, 2]
dev5 = [0, 0, 0.1, 0, 0]

#####

fig, ax = plt.subplots()
ax.errorbar(x, y1, yerr=dev1, marker="^", markersize=4, linestyle=" ", capsize=4, capthick=2, color="darkorange", label='line1')
ax.errorbar(x, y2, yerr=dev2, marker="s", markersize=4, linestyle=" ", capsize=4, capthick=2, color="green", label='line2')
ax.errorbar(x, y3, yerr=dev3, marker="v", markersize=4, linestyle=" ", capsize=4, capthick=2, color="blue", label='line3')
ax.errorbar(x, y4, yerr=dev4, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="brown", label='line4')
ax.errorbar(x, y5, yerr=dev5, marker="o", markersize=4, linestyle=" ", capsize=4, capthick=2, color="yellow", label='line5')

## NEW - First flipped the rows and columns...
handles, labels = ax.get_legend_handles_labels()
import itertools

def flip(items, ncol):
    return itertools.chain(*[items[i::ncol] for i in range(ncol)])
ax.legend(flip(handles, 3), flip(labels, 3), ncol=3)

## Get the handles and labels
handles1, labels1 = ax.get_legend_handles_labels()
handles1 = [h[0] for h in handles1]
ncols = 3
nlines = 5  ## This should be the number of entries you have = 5

leg1 = ax.legend(handles=handles1[:nlines//ncols * ncols], labels=labels1[:nlines//ncols * ncols], ncol=ncols)
ax.add_artist(leg1)
leg2 = ax.legend(handles=handles1[nlines//ncols * ncols:], labels=labels1[nlines//ncols * ncols:], ncol=nlines-nlines//ncols*ncols)

leg2.remove()
leg1._legend_box._children.append(leg2._legend_handle_box)
leg1._legend_box.stale = True

plt.show()

enter image description here

Redox
  • 9,321
  • 5
  • 9
  • 26