Python Matplotlib figure title overlaps axes label when using twiny - python

I am trying to plot two separate quantities on the same graph using twiny as follows:
fig = figure()
ax = fig.add_subplot(111)
ax.plot(T, r, 'b-', T, R, 'r-', T, r_geo, 'g-')
ax.set_yscale('log')
ax.annotate('Approx. sea level', xy=(Planet.T_day*1.3,(Planet.R)/1000), xytext=(Planet.T_day*1.3, Planet.R/1000))
ax.annotate('Geostat. orbit', xy=(Planet.T_day*1.3, r_geo[0]), xytext=(Planet.T_day*1.3, r_geo[0]))
ax.set_xlabel('Rotational period (hrs)')
ax.set_ylabel('Orbital radius (km), logarithmic')
ax.set_title('Orbital charts for ' + Planet.N, horizontalalignment='center', verticalalignment='top')
ax2 = ax.twiny()
ax2.plot(v,r,'k-')
ax2.set_xlabel('Linear speed (ms-1)')
show()
and the data is presented fine, but I am having the problem that the figure title is overlapping with the axes labels on the secondary x axis so that it's barely legible (I wanted to post a picture example here, but I don't have a high enough rep yet).
I'd like to know if there's a straightforward way to just shift the title directly up a few tens of pixels, so that the chart looks prettier.

I'm not sure whether it is a new feature in later versions of matplotlib, but at least for 1.3.1, this is simply:
plt.title(figure_title, y=1.08)
This also works for plt.suptitle(), but not (yet) for plt.xlabel(), etc.

Forget using plt.title and place the text directly with plt.text. An over-exaggerated example is given below:
import pylab as plt
fig = plt.figure(figsize=(5,10))
figure_title = "Normal title"
ax1 = plt.subplot(1,2,1)
plt.title(figure_title, fontsize = 20)
plt.plot([1,2,3],[1,4,9])
figure_title = "Raised title"
ax2 = plt.subplot(1,2,2)
plt.text(0.5, 1.08, figure_title,
horizontalalignment='center',
fontsize=20,
transform = ax2.transAxes)
plt.plot([1,2,3],[1,4,9])
plt.show()

I was having an issue with the x-label overlapping a subplot title; this worked for me:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 1)
ax[0].scatter(...)
ax[1].scatter(...)
plt.tight_layout()
.
.
.
plt.show()
before
after
reference:
https://matplotlib.org/users/tight_layout_guide.html

ax.set_title('My Title\n', fontsize="15", color="red")
plt.imshow(myfile, origin="upper")
If you put '\n' right after your title string, the plot is drawn just below the title. That might be a fast solution too.

You can use pad for this case:
ax.set_title("whatever", pad=20)

Just use plt.tight_layout() before plt.show(). It works well.

A temporary solution if you don't want to get into the x, y position of your title.
Following worked for me.
plt.title('Capital Expenditure\n') # Add a next line after your title
kudos.

Using the plt.tight_layout() before the plt.show() works for me well.
you can even make it better and visible by adding a padding
ax.set_title("title", pad=15)

Related

Python matplotlib title at wrong place [duplicate]

I am trying to plot two separate quantities on the same graph using twiny as follows:
fig = figure()
ax = fig.add_subplot(111)
ax.plot(T, r, 'b-', T, R, 'r-', T, r_geo, 'g-')
ax.set_yscale('log')
ax.annotate('Approx. sea level', xy=(Planet.T_day*1.3,(Planet.R)/1000), xytext=(Planet.T_day*1.3, Planet.R/1000))
ax.annotate('Geostat. orbit', xy=(Planet.T_day*1.3, r_geo[0]), xytext=(Planet.T_day*1.3, r_geo[0]))
ax.set_xlabel('Rotational period (hrs)')
ax.set_ylabel('Orbital radius (km), logarithmic')
ax.set_title('Orbital charts for ' + Planet.N, horizontalalignment='center', verticalalignment='top')
ax2 = ax.twiny()
ax2.plot(v,r,'k-')
ax2.set_xlabel('Linear speed (ms-1)')
show()
and the data is presented fine, but I am having the problem that the figure title is overlapping with the axes labels on the secondary x axis so that it's barely legible (I wanted to post a picture example here, but I don't have a high enough rep yet).
I'd like to know if there's a straightforward way to just shift the title directly up a few tens of pixels, so that the chart looks prettier.
I'm not sure whether it is a new feature in later versions of matplotlib, but at least for 1.3.1, this is simply:
plt.title(figure_title, y=1.08)
This also works for plt.suptitle(), but not (yet) for plt.xlabel(), etc.
Forget using plt.title and place the text directly with plt.text. An over-exaggerated example is given below:
import pylab as plt
fig = plt.figure(figsize=(5,10))
figure_title = "Normal title"
ax1 = plt.subplot(1,2,1)
plt.title(figure_title, fontsize = 20)
plt.plot([1,2,3],[1,4,9])
figure_title = "Raised title"
ax2 = plt.subplot(1,2,2)
plt.text(0.5, 1.08, figure_title,
horizontalalignment='center',
fontsize=20,
transform = ax2.transAxes)
plt.plot([1,2,3],[1,4,9])
plt.show()
I was having an issue with the x-label overlapping a subplot title; this worked for me:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(2, 1)
ax[0].scatter(...)
ax[1].scatter(...)
plt.tight_layout()
.
.
.
plt.show()
before
after
reference:
https://matplotlib.org/users/tight_layout_guide.html
ax.set_title('My Title\n', fontsize="15", color="red")
plt.imshow(myfile, origin="upper")
If you put '\n' right after your title string, the plot is drawn just below the title. That might be a fast solution too.
You can use pad for this case:
ax.set_title("whatever", pad=20)
Just use plt.tight_layout() before plt.show(). It works well.
A temporary solution if you don't want to get into the x, y position of your title.
Following worked for me.
plt.title('Capital Expenditure\n') # Add a next line after your title
kudos.
Using the plt.tight_layout() before the plt.show() works for me well.
you can even make it better and visible by adding a padding
ax.set_title("title", pad=15)

ax.set_xlabel and ax.set_ylabel not working with pandas plot

I have found similar questions previously, but I haven't managed to find an answer that has worked for me.
I am plotting directly from my data frame and would like to label my axis. This is the code I am using:
fig,ax = plt.subplots()
ax = plt.gca()
ax.set_xlabel("Time (s)")
ax.set_ylabel("Normalised Vertical Acceleration")
data.plot(kind='line', x='time', y='accel_y', ax=ax)
The graph generated only has "cycle" as the x-axis label and no y-axis label. Is there something that I'm doing wrong? Or is there a better method?
Thanks in advance.
Edited answer: Based on your updated question
You don't need additionally ax = plt.gca(). Then, first plot the data and then set the axis labels
fig, ax = plt.subplots()
data.plot(kind='line', x='time', y='accel_y', ax=ax)
ax.set_xlabel("Time (s)")
ax.set_ylabel("Normalised Vertical Acceleration")
#Sheldore's answer didn't work for me.
Instead, we need to use the inbuild function parameter:
fig, ax = plt.subplots()
data.plot(kind='line', x='time', y='accel_y', ax=ax,
ylabel="Normalised Vertical Acceleration",
xlabel="Time (s)")
I would report this as a bug to Pandas, which might be version-specific.

How can I make my axes visible with matplotlib?

I am using matplotlib.pyplot to plot some graphs and for some reasons I can't see the lines of the axes, although I can see the xticks and yticks. Important to note that I am using python notebook, and usually I try to visualize my graphs with the function (%matplotlib inline)
Here is an example figure that I get (without the axes):
Here is the code I used to produce this figure:
fig, ax = plt.subplots(1,1, figsize=(7.5,6), sharey=False, sharex=False, edgecolor='k', frameon=True)
ax.plot(np.array(frequency_vec), before_LTP, 'b-o', label='Before');
ax.plot(np.array(frequency_vec), After_LTP, 'r-o', label='After');
plt.yticks([1,2,3,4,5,6,7,8], ['1','2','3','4','5','6','7','0'], fontsize=14)
plt.xticks(fontsize=14)
plt.rcParams['axes.edgecolor']='k'
ax.patch.set_visible(False)
ax.grid(False)
ax.set_frame_on(True)
ax.set_xlim(0, 110)
ax.set_ylim(1,(Number_of_pulses)+2)
ax.legend(loc='best', fontsize=15)
plt.xticks([12.5,25,50,75,100], ['12.5','25','50','75','100']);
So again - How can I make my axes-lines to be visible?
Thanks!
Do you have some special setting in your matplotlibrc file such as edgecolor?
import matplotlib as mpl
print mpl.rcParams['axes.edgecolor']
If it's 'w' (white) set it to 'k' (black)
If it's not edgecolor, do you have frameon = False? Try something like this:
fig, ax = subplots()
ax.plot([1,2,4],[4,5,6], 'r^-')
ax.set_frame_on(True)
I wrote that and it worked
plt.axes().get_xaxis().set_visible(False)
plt.axes().get_yaxis().set_visible(False)
Well, just write 'True' instead of 'False'.

How to draw grid lines behind matplotlib bar graph

x = ['01-02', '02-02', '03-02', '04-02', '05-02']
y = [2, 2, 3, 7, 2]
fig, ax = plt.subplots(1, 1)
ax.bar(range(len(y)), y, width=0.3,align='center',color='skyblue')
plt.xticks(range(len(y)), x, size='small')
plt.savefig('/home/user/graphimages/foo2.png')
plt.close()
I want to draw grid lines (of x & y) behind the bar graph.
To add a grid you simply need to add
ax.grid()
If you want the grid to be behind the bars then add
ax.grid(zorder=0)
ax.bar(range(len(y)), y, width=0.3, align='center', color='skyblue', zorder=3)
The important part is that the zorder of the bars is greater than grid. Experimenting it seems zorder=3 is the lowest value that actually gives the desired effect. I have no idea why zorder=1 isn't sufficient.
EDIT:
I have noticed this question has already been answered here using a different method although it suffers some link rot. Both methods yield the same result as far as I can see but andrew cooke's answer is more elegant.
I am suggesting another solution since the most voted answer did not work for me. You can use the following code to set the gridlines behind the plot.
ax.set_axisbelow(True)
ax.grid(color='gray', linestyle='dashed')
I got this code from this answer.
plt.grid(True, color = "grey", linewidth = "1.4", linestyle = "-.")
This worked for me, the grid lines will be in grey border color,if you want can change border design to linestyle = ".."
Like this
plt.grid(True, color = "grey", linewidth = "1.4", linestyle = "..")
Summing up entire code block:
fig, ax = plt.subplots(1, 1)
ax.bar(range(len(y)), y, width=0.3,align='center',color='skyblue')
plt.xticks(range(len(y)), x, size='small')
plt.grid(True, color = "grey", linewidth = "1.4", linestyle = "-.")
plt.savefig('/home/user/graphimages/foo2.png')
plt.close()
use .grid() it makes the order go to 0 (back)
ax.grid(zorder=0)
ax.grid(zorder=0) Woud work. But First Place the Bar and then Place the Grid.Not the orther way.
ax = df.plot.bar(x='Index', y='Values', rot=90)
ax.grid(zorder=0)
I took some currency Correlation with Year and Sorted it as my Data Frame df, and below is the result of the code run.

matplotlib add rectangle to Figure not to Axes

I need to add a semi transparent skin over my matplotlib figure. I was thinking about adding a rectangle to the figure with alpha <1 and a zorder high enough so its drawn on top of everything.
I was thinking about something like that
figure.add_patch(Rectangle((0,0),1,1, alpha=0.5, zorder=1000))
But I guess rectangles are handled by Axes only. is there any turn around ?
Late answer for others who google this.
There actually is a simple way, without phantom axes, close to your original wish. The Figure object has a patches attribute, to which you can add the rectangle:
fig, ax = plt.subplots(nrows=1, ncols=1)
ax.plot(np.cumsum(np.random.randn(100)))
fig.patches.extend([plt.Rectangle((0.25,0.5),0.25,0.25,
fill=True, color='g', alpha=0.5, zorder=1000,
transform=fig.transFigure, figure=fig)])
Gives the following picture (I'm using a non-default theme):
The transform argument makes it use figure-level coordinates, which I think is what you want.
You can use a phantom axes on top of your figure and change the patch to look as you like, try this example:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
ax.set_zorder(1000)
ax.patch.set_alpha(0.5)
ax.patch.set_color('r')
ax2 = fig.add_subplot(111)
ax2.plot(range(10), range(10))
plt.show()
If you aren't using subplots, using gca() will work easily.
from matplotlib.patches import Rectangle
fig = plt.figure(figsize=(12,8))
plt.plot([0,100],[0,100])
plt.gca().add_patch(Rectangle((25,50),15,15,fill=True, color='g', alpha=0.5, zorder=100, figure=fig))

Categories