Removing frame while keeping axes in pyplot subplots - matplotlib

I am creating a figure with 3 subplots, and was wondering if there is any way of removing the frame around them, while keeping the axes in place?

If you want to remove the axis spines, but not the other information (ticks, labels, etc.), you can do that like so:
fig, ax = plt.subplots(7,1, sharex=True)
t = np.arange(0, 1, 0.01)
for i, a in enumerate(ax):
a.plot(t, np.sin((i + 1) * 2 * np.pi * t))
a.spines["top"].set_visible(False)
a.spines["right"].set_visible(False)
a.spines["bottom"].set_visible(False)
or, more easily, using seaborn:
fig, ax = plt.subplots(7,1, sharex=True)
t = np.arange(0, 1, 0.01)
for i, a in enumerate(ax):
a.plot(t, np.sin((i + 1) * 2 * np.pi * t))
seaborn.despine(left=True, bottom=True, right=True)
Both approaches will give you:

Try plt.box(on=None) It removed only the bounding box (frame) around plot, which is what I was trying to do.
plt.axis('off') removed tick labels and the bounding box, which wasn't what I was looking to accomplish.

You can achieve something like this with the axis('off') method of an axis handle. Is this the kind of thing you are after? (example code below the figure).
fig, ax = plt.subplots(7,1)
t = np.arange(0, 1, 0.01)
for i, a in enumerate(ax):
a.plot(t, np.sin((i+1)*2*np.pi*t))
a.axis('off')
plt.show()

Try
ax.set_frame_on(False)
It removes the box frame around any plot, but the x and y ticks remain.

Related

y and x axis subplots matplotlib

A quite basic question about ticks' labels for x and y-axis. According to this code
fig, axes = plt.subplots(6,12, figsize=(50, 24), constrained_layout=True, sharex=True , sharey=True)
fig.subplots_adjust(hspace = .5, wspace=.5)
custom_xlim = (-1, 1)
custom_ylim = (-0.2,0.2)
for i in range(72):
x_data = ctheta[i]
y_data = phi[i]
y_err = err_phi[i]
ax = fig.add_subplot(6, 12, i+1)
ax.plot(x_data_new, bspl(x_data_new))
ax.axis('off')
ax.errorbar(x_data,y_data, yerr=y_err, fmt="o")
ax.set_xlim(custom_xlim)
ax.set_ylim(custom_ylim)
I get the following output:
With y labels for plots on the first column and x labels for theone along the last line, although I call them off.
Any idea?
As #BigBen wrote in their comment, your issue is caused by you adding axes to your figure twice, once via fig, axes = plt.subplots() and then once again within your loop via fig.add_subplot(). As a result, the first set of axes is still visible even after you applied .axis('off') to the second set.
Instead of the latter, you could change your loop to:
for i in range(6):
for j in range(12):
ax = axes[i,j] # these are the axes created via plt.subplots(6,12,...)
ax.axis('off')
# … your other code here

How to stack the graphs in such a way that the share a common scale along x-axis

The following code is for generating the 3 subplots. And on all the 3 subplots scale is mentioned. I want to stack them in such a way that x-axis and y-axis scale appear once like this. Can I get this plot with plt.subplot() or fig.add_axes is compulsory for this? I actually want to do this with subplots because in fig.add_subplot I havve to specify the width and height of each plot that I don't want.
`fig,axes = plt.figure(nrow=3, ncolmn=1)
ax1 = fig.add_subplot(311)
ax2 = fig.add_subplot(312)
ax3 = fig.add_subplot(313)
ind1 =[1,2,3]
ind2 = [4,5,6]
for i in range(len(3)):
data1=np.load(..)
data2=np.load(..)
axes[i].plot(data1, data2)`
Here is one solution using subplots_adjust where you put the space between two plots to 0 using hspace. Also, use sharex=True to have a shared x-axis
fig, axes = plt.subplots(nrows=3, ncols=1,sharex=True)
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
for i, ax in enumerate(axes.ravel()): # or axes.flatten() or axes.flat
ax.plot(x, y, label='File %d' %i)
ax.legend()
fig.text(0.5, 0.01, 'X-label', ha='center')
fig.text(0.01, 0.5, 'Y-label', va='center', rotation='vertical')
plt.tight_layout() # To get a better spacing between the subplots
plt.subplots_adjust(hspace=.0)

How to force a graph within a grid in matplotlib?

I have a grid that looks like this
fig = plt.figure()
ax = fig.gca()
ax.set_xticks(numpy.arange(-5,6,1))
ax.set_yticks(numpy.arange(-5,6,1))
plt.grid(True)
When plotting an exponential function, obviously the function's values grow larger than the grid very quickly, and my grid ticks get distorted. I want the grid to be fixed, and only that part of the function to be graphed which fits inside of the grid. Is this possible?
Thanks in advance.
You can set the limits of the axes:
fig = plt.figure()
ax = fig.gca()
# Exponential plot:
x = linspace(-5, 5, 100)
y = power(2, x)
ax.plot(x, y)
ax.set_xticks(numpy.arange(-5,6,1))
ax.set_yticks(numpy.arange(-5,6,1))
ax.set_xlim(-5, 6)
ax.set_ylim(-5, 6)
plt.grid(True)

Manipulation on vertical space in matplotlib subplots

I want to reduce the verticalspacing between subplot. Surfing along the web I just have found how to reduce the horizontal spacing, something like
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently, "plt.tight_layout()"
fig.subplots_adjust(hspace=0.5)
plt.show()
The hspace thing is the one that manipulates such behaviour, but apparently there's no vspace.
EDIT:
This does not reduce the space between the y-axis, that is what I want to manipulate.
As you said in your question hspace reduces the vertical spacing between subplots. The equivalent for horizontal spacing between subplots is wspace. Below is an example:
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(nrows=2, ncols=2)
fig.tight_layout()
ax1.plot(x, y)
ax2.scatter(x, y)
ax3.scatter(x, y)
ax4.scatter(x, y)
fig.subplots_adjust(wspace=0.2)
plt.show()
Using a value for 1 for wspace gives
Using 0.2 as the value of wspace gives
An alternative approach is to pass the gridspec_kw argument a dict with keys wspace / hspace:
Example
fig, axes = plt.subplots(nrows=2, ncols=2, gridspec_kw={'hspace': 0.2, 'wspace': 0.9})
plt.tight_layout()
for ax, color in zip(axes.ravel(), list('rgbk')):
ax.scatter(np.arange(100), np.random.randn(100), color=color)
If I understood your question correctly, you want to reduce the vertical spacing, which is not what I have seen in all of the answers above.
If I am correct, you should reduce the hspace from 0.5 to 0.2, for instance. That's because hspace does not stand for horizontal spacing, it stands for height spacing, which is what you need.

how to avoid some function in the legend?

I need to include a line into a figure every time a button is clicked (I'm using pyqt4), this line has to be labeled and I also need to compare these lines with a constant function. Here is what I've tried:
labels = []
fig = plt.figure()
ax = fig.add_subplot(111, axisbg='white')
ax.hold(True)
def function(k):
x = np.linspace(0, 2, 100)
y = np.sin(k * np.pi * x) * np.exp(-5 * x)
labels.append('k = {}'.format(k))
ax.plot(x, y)
# reference line
plt.axhline(y=0.1, c='k', linestyle='--')
plt.legend(labels)
for i in range(0,5):
function(i)
plt.show()
The result:
There is a simple way to skip the constant line marker in the legend frame?
Maybe I'm not following but it doesn't look like your reference line axhline(y=0.1, ...) is included in the legend.
I would set this separately, no reason to redraw it every time you plot a new line. Also try passing the label inside the plot function
fig = plt.figure()
ax = fig.add_subplot(111, axisbg='white')
ax.hold(True)
# reference line - only draw this once
plt.axhline(y=0.1, c='k', linestyle='--')
def function(k):
x = np.linspace(0, 2, 100)
y = np.sin(k * np.pi * x) * np.exp(-5 * x)
ax.plot(x, y, linestyle='-', label='k = {}'.format(k)) # set label attribute for line
for i in range(0,5):
function(i)
plt.legend() # you only need to call this once, it will generate based on the label assigned to line objects
plt.show()
Note: If you want to do this interactively (i.e. draw on a button press) then you'll have to call plt.legend() upfront and call plt.draw() after each new line is added, that way it'll update the legend.
This is because there are actually 10 lines in your plot but your legend only shows 5 labels. If you check this by putting the label in the plot and axhline commands like this.
def function(k):
x = np.linspace(0, 2, 100)
y = np.sin(k * np.pi * x) * np.exp(-5 * x)
ax.plot(x, y, label='k = {}'.format(k))
# reference line
ax.axhline(y=0.1, c='k', linestyle='--', label='reference')
ax.legend()
print "number of lines in plot: {}".format(len(ax.lines))
Because you set the Axes.hold property to True, the Axes is not cleared, but a new line is added to Axes object every time you call these commands. This may be faster but you have to be careful to avoid adding duplicate artists. A simple solution would be to split the drawing in two functions: one to create an empty plot and one to add a line.
import matplotlib.pyplot as plt
import numpy as np
def init_plot(ax):
ax.hold(True)
ax.axhline(y=0.1, c='k', linestyle='--', label='reference')
ax.legend()
def add_line(ax, k):
x = np.linspace(0, 2, 100)
y = np.sin(k * np.pi * x) * np.exp(-5 * x)
ax.plot(x, y, label='k = {}'.format(k))
ax.legend()
def main():
fig = plt.figure()
ax = fig.add_subplot(111, axisbg='white')
init_plot(ax)
for i in range(0,5):
add_line(ax, i)
plt.show()
#raw_input('please press enter\n') # for OS-X
if __name__ == "__main__":
main()
I recommend to read the Artist tutorial and of course the Legend guide.