Displaying Main and Subplot Titles in matplotlib - python

As shown in the screenshot we are seeing only one title - for one of the two subplots. I am missing some detail on how to display the following three titles:
Overall plot
subplot 1
subplot 2
Here is relevant code for subplots and titles:
fig = plt.figure()
fig.suptitle('Power Iteration Clustering Inputs And Outputs') #NO show
ax = fig.add_subplot(211)
self.plotInputCircles(ax)
ax.set_title('Input Circles Data',fontsize='medium') #Shows up!
ax = fig.add_subplot(212)
self.plotOutputs(ax)
ax.set_title('Output Pseudo Eigenvector',fontsize='medium') #NO show
plt.subplots_adjust(hspace=0.1, wspace=0.2)
plt.show()
UPDATE the subroutines are corrupting the title displays (as suspected by #cel) . Per suggesion of #cel I am posting an answer stating as much.

The problem had nothing to do with titles. Per hint by #cel I looked more closely at the two subroutines that generate the subplots. One of them had a sneaky list comprehension bug.
For readers here is updated info using a dummy sin/cos that works fine instead of the subroutines.
fig = plt.figure()
fig.suptitle('Power Iteration Clustering Inputs And Outputs')
ax = fig.add_subplot(211)
x = np.linspace(-2.5,2.5,100)
ax.plot(x, np.sin(x))
# self.plotInputCircles(ax)
ax.set_title('Labeled Input Circles Data',fontsize='medium')
ax = fig.add_subplot(212)
# self.plotOutputs(ax)
x = np.linspace(-2.5,2.5,100)
ax.plot(x, np.cos(x))
ax.set_title('Output Pseudo Eigenvector',fontsize='medium')
plt.subplots_adjust(hspace=0.5, wspace=1.0)
plt.show()

Related

Arrange plots produced by for loop where only the column is set in Matplotlib

Is there a way where I can arrange plots without specifying the number of rows but just the columns (3 plots in a row for n row)? I don't want to set a specific amount of rows because different dataframe will be used where the columns extracted to plot the charts is not constant. This section of the code is able to give me the plots but I can't find a way to arrange them.
for i, title in zip(df1.columns[2:7], df2.columns[67:72]):
ax = df1.plot.scatter(x='out_date', y=i, figsize = (8,5), title=title)
ax.set_xlabel('out date')
ax.set_ylabel('successes')
leg = ax.legend(bbox_to_anchor=(1.0,1.0), loc='upper left')
plt.xticks(rotation=90)
Besides that, when I tried saving the plots into a file, it will save each plots as a separate file, so, this is not a convenient solution. I am very new with this but I'm guessing a way to solve this is by using subplots as mentioned in one of the answers here, but again, I don't know how to loop it.
fig = ax.figure
fig.savefig("test plot{}.pdf".format(i), bbox_inches = 'tight')
Above is the code I used which is included in the for loop.
A lot to unpack in this question but any help is appreciated. Thank you.
I hope this answer help those who are struggling just like me.
cols = 3
cols_used = len(df1.columns[2:])
rows = cols_used//cols + 1
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
fig, axs = plt.subplots(rows, cols, figsize=(30,200))
for i, title, ax in zip(df1.columns[2:], df2.columns[:], axs.ravel()):
df1.plot.scatter(x='out_date', y=i, title=title, ax=ax)
ax.axvline(x=cutoff_date, color='r', label='Recent 20pct')
ax.set_xlabel('out date')
ax.set_ylabel('successes')
plt.show()
fig.savefig('out plots.png', dpi = 300)
Referenced tutorial can be found here.

Adding secondary y labels to heatmap in matplotlib [duplicate]

I'm trying to plot a two-dimensional array in matplotlib using imshow(), and overlay it with a scatterplot on a second y axis.
oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)
plt.figure()
ax1 = plt.gca()
ax1.imshow(twoDim, cmap='Purples', interpolation='nearest')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()
#This is the line that causes problems
ax2 = ax1.twinx()
#That's not really part of the problem (it seems)
oneDimX = oneDim.shape[0]
oneDimY = 4
ax2.plot(np.arange(0,oneDimX,1),oneDim)
ax2.set_yticks(np.arange(0,oneDimY+1,1))
ax2.set_yticklabels(np.arange(0,oneDimY+1,1))
If I only run everything up to the last line, I get my array fully visualised:
However, if I add a second y axis (ax2=ax1.twinx()) as preparation for the scatterplot, it changes to this incomplete rendering:
What's the problem? I've left a few lines in the code above describing the addition of the scatterplot, although it doesn't seem to be part of the issue.
Following the GitHub discussion which Thomas Kuehn has pointed at, the issue has been fixed few days ago. In the absence of a readily available built, here's a fix using the aspect='auto' property. In order to get nice regular boxes, I adjusted the figure x/y using the array dimensions. The axis autoscale feature has been used to remove some additional white border.
oneDim = np.array([0.5,1,2.5,3.7])
twoDim = np.random.rand(8,4)
plt.figure(figsize=(twoDim.shape[1]/2,twoDim.shape[0]/2))
ax1 = plt.gca()
ax1.imshow(twoDim, cmap='Purples', interpolation='nearest', aspect='auto')
ax1.set_xticks(np.arange(0,twoDim.shape[1],1))
ax1.set_yticks(np.arange(0,twoDim.shape[0],1))
ax1.set_yticklabels(np.arange(0,twoDim.shape[0],1))
ax1.grid()
ax2 = ax1.twinx()
#Required to remove some white border
ax1.autoscale(False)
ax2.autoscale(False)
Result:

How to get two subplots side-by-side in matplotlib?

I just used following code to plot 2 subplot:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,4))
ax1 = fig.add_subplot(121)
ax1.set_xlabel('Credit_History')
ax1.set_ylabel('Count of Applicants')
ax1.set_title("Applicants by Credit_History")
temp1.plot(kind='bar')
ax2 = fig.add_subplot(122)
temp2.plot(kind='bar')
ax2.set_xlabel('Credit_History')
ax2.set_ylabel('Probability of getting loan')
ax2.set_title("Probability of getting loan by credit history")
I am getting following output
I am getting 3 plots i.e. 2 subplots as I intended, however the second one empty with titles as described. And third one underneath the two with bars for temp2 without the titles.
What I want are two subplots side by side with titles as described. Wondering what I have done wrong?
I'm not able to reproduce this exactly unless I put plt.show() between creating the second axes instance and temp2.plot(kind='bar'). If you aren't calling plt.show() (or clearing the buffer in some other way) you should try
temp1.plot(kind='bar', ax=ax1)
temp2.plot(kind='bar', ax=ax2)
This should correctly use the two generated axes instances.

plot graph in a specific figure in python

Actually, I am not clear that
fig_1 = plt.figure()
plt.subplot(2,2,1)
...
Is the ploting like plt.subplot(2,2,1) and other plt. plot on the fig_1 or system will automatically create a new empty figure?
Then how to plot something in a specific figure, for example:
fig_1 = plt.figure()
fig_2 = plt.figure()
plt.subplot(2,2,1)
I want to subplot on fig_2.
You can access a certain figure by e.g.
ax_1_1 = fig_1.add_subplot(2,2,1)
but this has a slightly different syntax (compare plt.subplot() against fig.add_subplot())
So I would recommend to create figures with subplots already prepared vis plt.subplots which returns handles for figure and axes on the fly:
fig_1, axs_1 = plt.subplots(2, 2)
fig_2, axs_2 = plt.subplots(3, 4)
axs_1[0, 0].plot(range(10))
axs_2[2, 3].plot(range(100))
fig_1.suptitle('Figure 1')
fig_2.suptitle('Figure 2')
etc. ...
You can use figure.add_subplot which will return an ax linked to your figure on which you can plot your data. Look at this page to get a global view of the different objects used by matplotlib.

Update Existent Matplotlib Subplot with a user input

I am currently trying to implement a 'zoom' functionality into my code. By this I mean I would like to have two subplots side by side, one of which contains the initial data and the other which contains a 'zoomed in' plot which is decided by user input.
Currently, I can create two subplots side by side, but after calling for the user input, instead of updating the second subplot, my script is creating an entirely new figure below and not updating the second subplot. It is important that the graph containing data is plotted first so the user can choose the value for the input accordingly.
def plot_func(data):
plot_this = data
plt.close('all')
fig = plt.figure()
#Subplot 1
ax1 = fig.add_subplot(1,2,1)
ax1.plot(plot_this)
plt.show()
zoom = input("Where would you like to zoom to: ")
zoom_in = plot_this[0:int(zoom)]
#Subplot 2
ax2 = fig.add_subplot(1,2,2)
ax2.plot(zoom_in)
plt.show()
The code above is a simplified version of what I am hoping to do. Display a subplot, and let the user enter an input based on that subplot. Then either edit a subplot that is already created or create a new one that is next to the first. Again it is crucial that the 'zoomed in' subplot is alongside the first opposed to below.
I think it is not very convenient for the user to type in numbers for zooming. The more standard way would be mouse interaction as already provided by the various matplotlib tools.
There is no standard tool for zooming in a different plot, but we can easily provide this functionality using matplotlib.widgets.RectangleSelector as shown in the code below.
We need to plot the same data in two subplots and connect the RectangleSelector to one of the subplots (ax). Every time a selection is made, the data coordinates of the selection in the first subplot are simply used as axis-limits on the second subplot, effectiveliy proving zoom-in (or magnification) functionality.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets import RectangleSelector
def onselect(eclick, erelease):
#http://matplotlib.org/api/widgets_api.html
xlim = np.sort(np.array([erelease.xdata,eclick.xdata ]))
ylim = np.sort(np.array([erelease.ydata,eclick.ydata ]))
ax2.set_xlim(xlim)
ax2.set_ylim(ylim)
def toggle_selector(event):
# press escape to return to non-zoomed plot
if event.key in ['escape'] and toggle_selector.RS.active:
ax2.set_xlim(ax.get_xlim())
ax2.set_ylim(ax.get_ylim())
x = np.arange(100)/(100.)*7.*np.pi
y = np.sin(x)**2
fig = plt.figure()
ax = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
#plot identical data in both axes
ax.plot(x,y, lw=2)
ax.plot([5,14,21],[.3,.6,.1], marker="s", color="red", ls="none")
ax2.plot(x,y, lw=2)
ax2.plot([5,14,21],[.3,.6,.1], marker="s", color="red", ls="none")
ax.set_title("Select region with your mouse.\nPress escape to deactivate zoom")
ax2.set_title("Zoomed Plot")
toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='box', interactive=True)
fig.canvas.mpl_connect('key_press_event', toggle_selector)
plt.show()
%matplotlib inline
import mpld3
mpld3.enable_notebook()

Categories