2

I am adding plots to a figure within a loop, so when I add a legend to the figure, it is ordered in the same order that the plots were added. Instead I would like to order the legend, intuitively, as the plots are displayed in the figure. Some of the plots overlap and cross over each other in some cases, so when I say "as the plots are displayed in the figure", a more definitive definition would be to order the legends based on the last y-value of each plot.

Here is my code as of now:

heights = [3, 4]

algos = ["NegaMax w/o PV",
         "PVS w/o PV",
         "NegaMax w/ PV",
         "PVS w/ PV"]

# (H, B, Algo, Approx)
temp = np.swapaxes(results, 2, 3)

for i in range(temp.shape[0]):
    for j in range(temp.shape[2]):
        plt.plot(temp[i][-1][j], label="{} (H = {})".format(algos[j], heights[i]))

plt.title("Num of Evaluations for each Algorithm at each Height with Maximum Branching Factor")
plt.xlabel("\'Aprox\' Value")
plt.ylabel("Number of Evaluations")
plt.xticks(np.arange(7), np.arange(0, 301, 50))
plt.legend()
plt.show()

which displays this figure:

enter image description here

Here is myresults numpy array.

KOB
  • 4,084
  • 9
  • 44
  • 88

1 Answers1

1

The idea would be to obtain the order of the elements from the last data row, e.g. using numpy.argsort, order the handles and labels accordingly and supply the ordered handles and labels to the legend.

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0.,3.4)
phis = np.linspace(0.3,6.2,5)
y = np.array([np.sin(x+phi) for phi in phis]).T

labels = ["sin({:.2f}*x)".format(phi) for phi in phis]

plt.plot(x,y, label="unknown")

order = np.argsort(y[-1,:])[::-1]
h, l = plt.gca().get_legend_handles_labels()
plt.legend(handles=list(np.array(h)[order]),labels=list(np.array(labels)[order]))
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712