Overlaying matplotlib plot from multiple function calls while also plotting them separately - python

I have a function which plots and displays the distribution using the distplot from seaborn. it looks like this
def getPlot(data):
x=sns.distplot(data, hist=False)
plt.show()
return x
every time I call the function I get a plot of the distribution.
I want some help in modifying the function so that at the end of calling the function multiple times I should get an extra plot which is the combination of all the previous plots.
So if my function calls were
getPlot(data1)
getPlot(data2)
getPlot(data3)
I should get the individual plots for the data as I call the function and also at the very end I want the plots for the 3 data to be superimposed on each other.
Just moving plt.show() outside the function will not suffice because I want individual plots of the separate data as well as one figure that contains all the data.

Since you have to keep both a separate plot and a joint one of your data you have to plot each dataset twice. Once in a separate axes and once in a common one.
What I would do is create a figure and an axes into which everything will be plotted together. Then pass that axes object into the function, and make the function plot into the axes as well as into a new figure:
def plot_twice(data, ax_all):
# first plot into the common axes
sns.distplot(data, hist=False, ax=ax_all)
# and create a new figure and axes for a standalone plot
fig,ax = plt.subplots()
x = sns.distplot(data, hist=False, ax=ax)
return x
# create axes for the common plot
fig,ax_all = plt.subplots()
# now plot the things
getPlot(data1, ax_all)
getPlot(data2, ax_all)
getPlot(data3, ax_all)
# only call blocking plt.show() at the end
plt.show()
It doesn't seem feasible to copy plots from one axes to the other with matplotlib (see e.g. this or this), so unless the plotting takes an excessive amount of time or memory I'd just plot the data twice for simplicity.

Related

What does the 'single' mean here?

Here is the instruction:
a string "fig_type", which is one of the two values: "single" or "subplots".
The input argument "fig_type" determines how to draw the plots:
if "fig_type" is "single", you should produce one set of axes, draw all the plots together in the same axes, and differentiate them e.g. by line or marker colour or style.
if "fig_type" is "subplots", you should produce 𝑟
r
different sets of axes (in the same figure), so that each plot is drawn in a different subplot. Choose how to set up your subplots so that all plots are sufficiently large and readable.
Then I write a code like that, I'm not quite sure if that's how it should be written, and I'm not sure what single means in this context.
if fig_type =='single':
fig, ax = plt.plot()
else:
fig, ax = plt.subplots()

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

Why are my plots being displayed separately, rather than on the same graph?

I have created two line plots with this dataset. The first lineplot shows the number of flight accidents in a given year. The second lineplot shows the number of fatalities in a given year. I want to put both line plots on the same graph. This is the code I have used:
fatalities=df[['Fatalities','Date']]
fatalities['Year of Fatality']=fatalities['Date'].dt.year
fatalities.drop('Date',inplace=True)
fatalities.set_index('Year of Fatality',inplace=True)
fatalities.sort_index(inplace=True)
plt.figure(figsize=(12,9))
plt.title("Number of Flight Accidents Since 1908",fontsize=20)
plt.ylabel("Number of Flight Accidents")
plt.xlabel("Year")
plt.xticks(year.index,rotation=90)
year.plot()
fatalities.plot()
plt.show()
What I get are two plots, with on above the other: the plot which shows the number of fatalities and the plot which shows the number of flight accidents.
What I want is one graph that shows the two line plots. Any help would be much appreciated. (Side note: how can I rotate the xticks 90 degrees? I used the rotation argument in the plt.xticks() but this had zero affect).
Given the use of .plot() and variables called df, I assume you're using pandas dataframes (if that's not the case, the answer still probably applies, look up the docs for your plot function).
Pandas' plot by default puts the plots in their own axis, unless you pass one to draw on via the ax attribute:
fig, ax = plt.subplots()
year.plot(ax=ax)
fatalities.plot(ax=ax)

How to subplot multiple graphs when calling a function that plots the graph?

I have a function that plots a graph. I can call this graph with different variables to alter the graph. I'd like to call this function multiple times and plot the graphs along side each other but not sure how to do so
def plt_graph(x, graph_title, horiz_label):
df[x].plot(kind='barh')
plt.title(graph_title)
plt.ylabel("")
plt.xlabel(horiz_label)
plt_graph('gross','Total value','Gross (in millions)')
In case you know the number of plots you want to produce beforehands, you can first create as many subplots as you need
fig, axes = plt.subplots(nrows=1, ncols=5)
(in this case 5) and then provide the axes to the function
def plt_graph(x, graph_title, horiz_label, ax):
df[x].plot(kind='barh', ax=ax)
Finally, call every plot like this
plt_graph("framekey", "Some title", "some label", axes[4])
(where 4 stands for the fifth and last plot)
I have created a tool to do this really easily. I use it all the time in jupyter notebooks and find it so much neater than a big column of charts. Copy the Gridplot class from this file:
https://github.com/simonm3/analysis/blob/master/analysis/plot.py
Usage:
gridplot = Gridplot()
plt.plot(x)
plt.plot(y)
It shows each new plot in a grid with 4 plots to a row. You can change the size of the charts or the number per row. It works for plt.plot, plt.bar, plt.hist and plt.scatter. However it does require you use matplot directly rather than pandas.
If you want to turn it off:
gridplot.off()
If you want to reset the grid to position 1:
gridplot.on()
Here is a way that you can do it. First you create the figure which will contain the axes object. With those axes you have something like a canvas, which is where every graph will be drawn.
fig, ax = plt.subplots(1,2)
Here I have created one figure with two axes. This is a one row and two columns figure. If you inspect the ax variable you will see two objects. This is what we'll use for all the plotting. Now, going back to the function, let's start with a simple dataset and define the function.
df = pd.DataFrame({"a": np.random.random(10), "b": np.random.random(10)})
def plt_graph(x, graph_title, horiz_label, ax):
df[x].plot(kind = 'barh', ax = ax)
ax.set_xlabel(horiz_label)
ax.set_title(graph_title)
Then, to call the function you will simply do this:
plt_graph("a", "a", "a", ax=ax[0])
plt_graph("b", "b", "b", ax=ax[1])
Note that you pass each graph that you want to create to any of the axes you have. In this case, as you have two, you pass the first to the first axes and so on. Note that if you include seaborn in your import (import seaborn as sns), automatically the seaborn style will be applied to your graphs.
This is how your graphs will look like.
When you are creating plotting functions, you want to look at matplotlib's object oriented interface.

How to add axes for subplot in matplotlib

I need to fit a function to a large number of datasets stored in several files and compare the fits. I open a file, read the columns and plot each fit as a subplot after fitting. Eventually I have a figure with lot of subplots showing all the fits. However, I need to see the fit and also the residual for each subplot like in the figure.
So far, I have the following. I thought I could add axes to subplot but it does not work. The function that I have works. But I do not know how to add axes to subplot to plot the residual with the fit as a subplot to the subplot.
def plotall(args):
x=args[0]
ydata=args[1]
chisq=args[2]
fit=args[3]
g1=args[4]
a=args[5]
ptitle=args[6]
axi = fig1.add_subplot(a1,b1,a+1)
axi.plot(x, ydata,'ko',markersize=2,label='Data')
axi.plot(x,fit,'m-',label='Fit')
axi.text(0.75,0.8,'T=%4.1f(K)'%ptitle, fontsize=7,transform = axi.transAxes)
axi.text(0.05,0.45,r'$\chi^2$=%3.1f'%chisq,fontsize=7,transform = axi.transAxes)
ytlist=np.linspace(min(ydata),max(ydata),4)
axi.set_yticks(ytlist)
axi.set_xlim([xlow,xhi])
xtlist=np.linspace(xlow,xhi,6)
axi.set_xticks(xtlist)
for label in (axi.get_xticklabels() + axi.get_yticklabels()):
label.set_fontname('Arial')
label.set_fontsize(5)
axi.legend(('Data','Fit'), 'upper left', shadow=False, fancybox=False,numpoints=1,
frameon = 0,labelspacing=0.01,handlelength=0.5,handletextpad=0.5,fontsize=6)

Categories