22
votes

I am pretty new to python and to the matplotlib library. I have created a scatter plot using matplotlib and now I wish to add caption a little below the X-axis. This is my code:

from matplotlib import pyplot as plt
import numpy as np
from pylab import *

file = open('distribution.txt', 'r')

txt="I need the caption to be present a little below X-axis"

x=[]
y=[]
for line in file:
    new=line.rstrip()
    mystring=new.split("\t")
    x.append(mystring[0])
    y.append(mystring[1])


fig = plt.figure()
ax1 = fig.add_axes((0.1,0.4,0.8,0.5))
ax1.set_title("This is my title")
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')
ax1.scatter(x,y, c='r')
fig.text(.05,.05,txt)
plt.xlim(0, 1.05)
plt.ylim(0, 2.5)
plt.show()

As you can see in the image my caption is way below the scatter plot, is there a way to bring it exactly below the X-axis? Also my scatter plot looks rectangular, is there a way to make it square like?

enter image description here

5

5 Answers

24
votes

Something like:

from matplotlib import pyplot as plt
import numpy as np

txt="I need the caption to be present a little below X-axis"

# make some synthetic data
x = np.linspace(0, 1, 512)
y = np.random.rand(512)*2.3 + .1

fig = plt.figure()
ax1 = fig.add_axes((0.1, 0.2, 0.8, 0.7))

ax1.set_title("This is my title")
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')

# make the edge colors match the facecolors
ax1.scatter(x,y, c='r', edgecolors='face')
# center text
fig.text(.5, .05, txt, ha='center')

# use OO interface    
ax1.set_xlim([0, 1.05])
ax1.set_ylim([0, 2.5])

# resize the figure to match the aspect ratio of the Axes    
fig.set_size_inches(7, 8, forward=True)

plt.show()

example result

might work. Making this easier to do is on the radar for mpl upstream, but we are still looking for someone to do it.

36
votes

You can simply use figtext. You can also change the value of x and y-axes as you want.

txt="I need the caption to be present a little below X-axis"
plt.figtext(0.5, 0.01, txt, wrap=True, horizontalalignment='center', fontsize=12)
13
votes

First, I feel weird posting an answer against the co-lead developer of matplotlib. Obviously, @tacaswell knows matplotlib far better than I ever will. But at the same time, his answer wasn't dynamic enough for me. I needed a caption that would always be based on the position of the xlabel, and couldn't just use text annotations.

I considered simply changing the xlabel to add a newline and the caption text, but that wouldn't clearly differentiate the caption, and you can't do things like change the text size or make it italic in the middle of a text string.

I solved this by using matplotlib's TeX capabilities. Here's my solution:

from matplotlib import pyplot as plt
from matplotlib import rc
import numpy as np
from pylab import *

rc('text', usetex=True)

file = open('distribution.txt', 'r')

txt="I need the caption to be present a little below X-axis"

x=[]
y=[]
for line in file:
    new=line.rstrip()
    mystring=new.split("\t")
    x.append(mystring[0])
    y.append(mystring[1])


fig = plt.figure()
ax1 = fig.add_axes((0.1,0.4,0.8,0.5))
ax1.set_title("This is my title")
ax1.set_xlabel(r'\begin{center}X-axis\\*\textit{\small{' + txt + r'}}\end{center}')
ax1.set_ylabel('Y-axis')
ax1.scatter(x,y, c='r')
plt.xlim(0, 1.05)
plt.ylim(0, 2.5)
plt.show()

I did the same thing with the random scatter plot from tacaswell's answer, and here's my result:

Scatter plot with caption

One warning: if you tweak this to take input string variables, the strings may not be properly escaped for use with TeX. Escaping LaTeX code is already covered on Stack Overflow, at https://stackoverflow.com/a/25875504/1404311 . I used that directly, and then could take arbitrary xlabels and captions.

3
votes

Another simple solution that I used when I couldn't figure out how to do it in a way that was designed...if that makes sense, was to just add some new lines to the xlabel plt.xlabel("xaxis label\n\n\n\ncaption") This just puts the caption a couple new lines under the x axis which makes it look like a caption even thought it's really part of the xaxis label

1
votes

as @Nicky V mentioned.

plt.xlabel('''Butterfly contract traded

Note: c1-c2-c3 indicates the position: long 2 times c2 and short c1 anc c3''')

Result:

enter image description here