1

I am trying to set the "suptitle" of my Matplotlib multi plot as shown below:

plt.gcf().suptitle("pc1\npc2", fontsize=10)

The following figure shows how it looks like:

enter image description here

Now instead of the 'pc2' on the next line, I would like to show a kind of Pseudo Legend, but without any decorations, just plain symbols as shown in a corresponding R plot below:

enter image description here

See the second row which shows a 'square' followed by the word MRP, another square followed by XRD, etc.? I am trying to replicate it (not exactly but close). As you can see in the line of code that I show above that the new line character "\n" pushes the title text string to the next line. If I can format the second line approximately using the marker symbols (square, triangle, star, etc.) then I am all set. The exact markers do not matter and I can use any marker that can be interpreted and shown as a symbol by the title string. the Marker vector that I chose is shown below (but can be changed to any set of 5 symbols):

markers_list = ["s", "o", "*", "^", "+"]

If you would like to see the entire Python code and more details, it can be seen in the following thread:

MatplotLib Seaborn Multiple Plot Formatting

I do not want to show the legend as discussed in that thread. A simple string representation on the second line would suffice.

Community
  • 1
  • 1
Bharat
  • 2,409
  • 6
  • 32
  • 57
  • Why don't you use a real legend with a dummy actor as e.g. explained here: https://stackoverflow.com/questions/22348229/matplotlib-legend-for-an-arrow – languitar Apr 25 '17 at 15:36
  • It seems more complicated not to use a legend than using a legend. So what is wrong with using the legend just as explained in the previous post you link to? – ImportanceOfBeingErnest Apr 25 '17 at 16:01
  • @ImportanceOfBeingErnest, The legend is confined to one of the many plots as you explained in the previous post. Whereas putting it up top and evenly spaced correctly conveys the information that it applies to all plots. Please correct me if I am wrong. – Bharat Apr 25 '17 at 17:01

1 Answers1

0

Here is an example using a legend on one of the plots but positioning it in figure coordinates.

enter image description here

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(12)
import seaborn.apionly as sns
plt.rcParams["figure.figsize"] = 7,3.5

markers_list = ["s", "o", "*", "^", "+"]
labels = ["MRP","XRD","Geochem","GC", "OR"]

fig, axes = plt.subplots(ncols=3)
for i, ax in enumerate(axes):
    a = np.random.normal(size=(66))
    sns.distplot(a, ax=ax, hist_kws={"ec":"k","fc":(i/3.,0,1-i/3.)})
    this_x= np.array([-1,0,1.5])
    data_x, data_y = ax.lines[0].get_data()
    this_y = np.interp(this_x, data_x, data_y)
    for i, m, l in zip(range(len(labels)), markers_list, labels):
        ax.plot(this_x, this_y-i*0.016,  marker=m, markersize = 3, 
                color="black", ls="", label=l)

fig.suptitle("pc1",x=0.5,y=0.98)

axes[0].legend(loc="lower center", ncol=5,
        bbox_to_anchor=(0.5,0.8),bbox_transform=plt.gcf().transFigure)
plt.tight_layout()
plt.subplots_adjust(top=0.8)
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • this will work, thank you. But I am getting double markers in the legend instead of one each as you show above, when I copied and pasted your code on my machine and ran it. Would you know why? I do not know how to paste the figure that I am getting since I cannot edit my original post anymore. – Bharat Apr 25 '17 at 17:47
  • I found the answer on stackoverflow :) I had to add numpoints=1 in the axs[0].legend call. Now the display is exactly as you show above. – Bharat Apr 25 '17 at 17:58
  • I'm using matplotlib 2.0 which has one legend point by default; you probably have an older version, which uses 2 points by default. In this case you can indeed use `numpoints` to get the desired result. You can edit your post using the edit button below it, although it's probably not needed anymore. – ImportanceOfBeingErnest Apr 25 '17 at 20:15