Search code examples
pythonmatplotlibsymbolsmarkers

How to show Matplotlib Marker symbols as a string


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.


Solution

  • 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()