matplotlib ylabels disappear upon creating second subplot - python

In the MWE below, the y-label and ticks disappear. It seems to happen only with a few specific combinations of twiny and pandas for the other plot. The MWE is easily solved by changing the order in which the two subplots are created, but in my full script this is not as straightforward.
Any ideas on why this is happening and how it can be solved?
df = pd.DataFrame(np.random.randn(100))
def plot_twin(ax):
ax.plot([0,1])
ax.set_ylabel('test')
# Add return time axis to plot
other_ax = ax.twiny()
return
def plot_df(df,ax):
df.plot(kind='box',ax=ax)
return
fig,(ax1,ax2) = plt.subplots(1,2)
plot_twin(ax2)
plot_df(df,ax1)

Related

How can I return a matplotlib figure from a function?

I need to plot changing molecule numbers against time. But I'm also trying to investigate the effects of parallel processing so I'm trying to avoid writing to global variables. At the moment I have the following two numpy arrays tao_all, contains all the time points to be plotted on the x-axis and popul_num_all which contains the changing molecule numbers to be plotted on the y-axis.
The current code I've got for plotting is as follows:
for i, label in enumerate(['Enzyme', 'Substrate', 'Enzyme-Substrate complex', 'Product']):
figure1 = plt.plot(tao_all, popul_num_all[:, i], label=label)
plt.legend()
plt.tight_layout()
plt.show()
I need to encapsulate this in a function that takes the above arrays as the input and returns the graph. I've read a couple of other posts on here that say I should write my results to an axis and return the axis? But I can't quite get my head around applying that to my problem?
Cheers
def plot_func(x, y):
fig,ax = plt.subplots()
ax.plot(x, y)
return fig
Usage:
fig = plot_func([1,2], [3,4])
Alternatively you may want to return ax. For details about Figure and Axes see the docs. You can get the axes array from the figure by fig.axes and the figure from the axes by ax.get_figure().
In addition to above answer, I can suggest you to use matplotlib animation.FuncAnimation method if you are working with the time series and want to make your visualization better.
You can find the details here https://matplotlib.org/api/_as_gen/matplotlib.animation.FuncAnimation.html

Black bar covering my x labels for matplotlib plot?

I am trying to play a figure and I am having a black box pop up on the bottom of the plot where the x labels should be. I tried this command from a similar question on here in the past:
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
But the problem was still the same. Here is my current code:
import pylab
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
df['date'] = df['date'].astype('str')
pos = np.arange(len(df['date']))
plt.bar(pos,df['value'])
ticks = plt.xticks(pos, df['value'])
And my plot is attached here. Any help would be great!
pos = np.arange(len(df['date'])) and ticks = plt.xticks(pos, df['value']) are causing the problem you are having. You are putting an xtick at every value you have in the data frame.
Don't know how you data looks like and what's the most sensible way to do this. ticks = plt.xticks(pos[::20], df['value'].values[::20], rotation=90) will put a tick every 20 rows that would make the plot more readable.
It actually is not a black bar, but rather all of your x-axis labels being crammed into too small of a space. You can try rotating the axis labels to create more space or just remove them all together.

Loop and plot GroupBy data with fixed axes in Jupyter

(In a Jupyter Notebook): I'd like to loop through the groups in a Pandas Groupby Object and plot their GPS coordinate on the same axes. First, I'd like to clear the figure each time and plot solely the data by group. In a second case, I'd like for them to accumulate and not be cleared.
Question 1: Unfortunately in the code below, the axes change every iteration. Anyone know how to keep the axes fixed?
Question 2: How do I keep vs clear iterations?
This is my starter code:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlabel('LON'); ax.set_ylabel('LAT')
ax.set_xlim(50, 100); ax.set_ylim(0 ,30)
plt.ion()
fig.show()
fig.canvas.draw()
for key, data in groups:
ax.clear()
ax.scatter(data.LON, data.LAT)

remove colorbars from plot

I wrote some code to create a png of a raster object (self[:] = a np array).
it's supposed to be a method, to easily make a plot
Problem with the code is that it runs fine the first time,
but when i run this method multiple times i get a picture with multiple legends.
I tried to get rid of it with delaxes, but this legend is really stubborn.
Any Idea's how to solve this are welcome
Here's the code:
def plot(self,image_out,dpi=150, rotate = 60):
xur = self.xur()
xll = self.xll()
yur = self.yur()
yll = self.yll()
fig = plt.figure()
#tmp = range(len(fig.axes))
#tmp = tmp[::-1]
#for x in tmp:
# fig.delaxes(fig.axes[x])
ax = fig.add_subplot(111)
cax = ax.imshow(self[:],cmap='jet', extent = [yll,yur,xll,xur],
interpolation = 'nearest')
cbar = fig.colorbar()
plt.xticks(rotation=70)
plt.tight_layout(pad = 0.25)
plt.savefig(image_out,dpi=dpi)
return
You need to close the plot. I had this same problem
After plt.savefig, add plt.close()
A better option is to specify to colorbar which axes you would like to see it render into, see the example here.
I encountered the same problem and the answers in another post solved it
remove colorbar from figure in matplotlib
Please refer to the second answer
I had a similar problem and played around a little bit. I came up with two solutions which might be slightly more elegant:
Clear the whole figure and add the subplot (+colorbar if wanted) again.
If there's always a colorbar, you can simply update the axes with autoscale which also updates the colorbar.
I've tried this with imshow, but I guess it works similar for other plotting methods.
In particular, I used the first approach, which is to clear the figure by clf() and then re-add the axis each time.
You can remove the colorbar by its .remove() method:
cbar = fig.colorbar()
...
cbar.remove()

In Python with Matplotlib how to check if a subplot is empty in the figure

I have some graphs created with NetworkX and show them on screen using Matplotlib. Specifically, since I don't know in advance how many graphs I need to show, I create a subplot on the figure on fly. That works fine. However, at some point in the script, some subplots are removed from the figure and the figure is shown with some empty subplots. I would like to avoid it, but I was not able to retrieve the subplots that are empty in the figure. Here is my code:
#instantiate a figure with size 12x12
fig = plt.figure(figsize=(12,12))
#when a graph is created, also a subplot is created:
ax = plt.subplot(3,4,count+1)
#and the graph is drawn inside it: N.B.: pe is the graph to be shown
nx.draw(pe, positions, labels=positions, font_size=8, font_weight='bold', node_color='yellow', alpha=0.5)
#many of them are created..
#under some conditions a subplot needs to be deleted, and so..
#condition here....and then retrieve the subplot to deleted. The graph contains the id of the ax in which it is shown.
for ax in fig.axes:
if id(ax) == G.node[shape]['idax']:
fig.delaxes(ax)
until here works fine, but when I show the figure, the result looks like this:
you can notice that there are two empty subplots there.. at the second position and at the fifth. How can I avoid it? Or.. how can I re-organize the subplots in such a way that there are no more blanks in the figure?
Any help is apreciated! Thanks in advance.
So to do this I would keep a list of axes and when I delete the contents of one I would swap it out with a full one. I think the example below solved the problem (or at least gives an idea of how to solve it):
import matplotlib.pyplot as plt
# this is just a helper class to keep things clean
class MyAxis(object):
def __init__(self,ax,fig):
# this flag tells me if there is a plot in these axes
self.empty = False
self.ax = ax
self.fig = fig
self.pos = self.ax.get_position()
def del_ax(self):
# delete the axes
self.empty = True
self.fig.delaxes(self.ax)
def swap(self,other):
# swap the positions of two axes
#
# THIS IS THE IMPORTANT BIT!
#
new_pos = other.ax.get_position()
self.ax.set_position(new_pos)
other.ax.set_position(self.pos)
self.pos = new_pos
def main():
# generate a figure and 10 subplots in a grid
fig, axes = plt.subplots(ncols=5,nrows=2)
# get these as a list of MyAxis objects
my_axes = [MyAxis(ax,fig) for ax in axes.ravel()]
for ax in my_axes:
# plot some random stuff
ax.ax.plot(range(10))
# delete a couple of axes
my_axes[0].del_ax()
my_axes[6].del_ax()
# count how many axes are dead
dead = sum([ax.empty for ax in my_axes])
# swap the dead plots for full plots in a row wise fashion
for kk in range(dead):
for ii,ax1 in enumerate(my_axes[kk:]):
if ax1.empty:
print ii,"dead"
for jj,ax2 in enumerate(my_axes[::-1][kk:]):
if not ax2.empty:
print "replace with",jj
ax1.swap(ax2)
break
break
plt.draw()
plt.show()
if __name__ == "__main__":
main()
The extremely ugly for loop construct is really just a placeholder to give an example of how the axes can be swapped.

Categories