How to can display two distplots next to each other? - python

I am unable to display two distplots next to each other, when plotted alone both work fine.
f, (ax1, ax2) = plt.subplots(1,2)
sns.distplot(df_reqd_data_0['Total_Hood_Group_Earnings'], ax=ax1)
plt.show()
sns.distplot(df_reqd_data_0['Total_Partner_Earnings'], ax=ax2 )
plt.show()

You need to call the plot.show() command once after both the distplot commands.
Remove the extra plot.show(), so that the code looks like this.
f, (ax1, ax2) = plt.subplots(1,2)
sns.distplot(df_reqd_data_0['Total_Hood_Group_Earnings'], ax=ax1)
sns.distplot(df_reqd_data_0['Total_Partner_Earnings'], ax=ax2 )
plt.show()
EDIT:
Apart from the extra plt.show(), I am not sure what is sns here. But just to illustrate my point and answer the question posted by the OP:
"How to can display two distplots next to each other?"
try this code,
import matplotlib.pyplot as plt
x = range(10)
y = range(10)
plt.subplot(2,1,1)
plt.plot(y)
plt.subplot(2,1,2)
plt.plot(x)
plt.show()
and you can see why it works.

Related

Plotting a boxplot and histogram side by side with seaborn

I'm trying to plot a simple box plot next to a simple histogram in the same figure using seaborn (0.11.2) and pandas (1.3.4) in a jupyter notebook (6.4.5).
I've tried multiple approaches with nothing working.
fig, ax = plt.subplots(1, 2)
sns.boxplot(x='rent', data=df, ax=ax[0])
sns.displot(x='rent', data=df, bins=50, ax=ax[1])
There is an extra plot or grid that gets put next to the boxplot, and this extra empty plot shows up any time I try to create multiple axes.
Changing:
fig, ax = plt.subplots(2)
Gets:
Again, that extra empty plot next to the boxplot, but this time below it.
Trying the following code:
fig, (axbox, axhist) = plt.subplots(1,2)
sns.boxplot(x='rent', data=df, ax=axbox)
sns.displot(x='rent', data=df, bins=50, ax=axhist)
Gets the same results.
Following the answer in this post, I try:
fig, axs = plt.subplots(ncols=2)
sns.boxplot(x='rent', data=df, ax=axs[0])
sns.displot(x='rent', data=df, bins-50, ax=axs[1])
results in the same thing:
If I just create the figure and then the plots underneath:
plt.figure()
sns.boxplot(x='rent', data=df)
sns.displot(x='rent', data=df, bins=50)
It just gives me the two plots on top of each other, which I assume is just making two different figures.
I'm not sure why that extra empty plot shows up next to the boxplot when I try to do multiple axes in seaborn.
If I use pyplot instead of seaborn, I can get it to work:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
ax1.hist(df['rent'], bins=50)
ax2.boxplot(df['rent'])
Results in:
The closest I've come is to use seaborn only on the boxplot, and pyplot for the histogram:
plt.figure(figsize=(8, 5))
plt.subplot(1, 2, 1)
sns.boxplot(x='rent', data=df)
plt.subplot(1, 2, 2)
plt.hist(df['rent'], bins=50)
Results:
What am I missing? Why can't I get this to work with two seaborn plots on the same figure, side by side (1 row, 2 columns)?
Try this function:
def creating_box_hist(column, df):
# creating a figure composed of two matplotlib.Axes objects (ax_box and ax_hist)
f, (ax_box, ax_hist) = plt.subplots(2, sharex=True, gridspec_kw={"height_ratios": (.15, .85)})
# assigning a graph to each ax
sns.boxplot(df[column], ax=ax_box)
sns.histplot(data=df, x=column, ax=ax_hist)
# Remove x axis name for the boxplot
ax_box.set(xlabel='')
plt.show()

How to plot using a prewritten library function into a subplot?

I've been stumbling around this issue for a while, but today I really want to figure out if it can be done.
Say you have a function from a library that does some plotting, such as:
def plotting_function():
fig, ax = plt.subplots()
ax.plot([1,2,3], [2,4,10])
return fig
If I want to add this single plot multiple times to my own subplots, how could I do this?
I'm not able to change the plotting_function, as it's from a library, so what I've tried is:
fig, axs = plt.subplots(1,3)
for i in range(3):
plt.sca(axs[i])
plotting_function()
plt.show()
This results in an empty subplot with the line graphs plotting separate.
Is there any simple answer to this problem? Thanks in advance.
I think you might be better off to monkey patch plt.subplots(), but it is possible to move a subplot from one figure to another. Here's an example, based on this post:
import matplotlib.pyplot as plt
from matplotlib.transforms import Bbox
def plotting_function1():
fig, ax = plt.subplots()
ax.plot([1,2,3], [2,4,10])
return fig
def plotting_function2():
fig, ax = plt.subplots()
ax.plot([10,20,30], [20,40,100])
return fig
def main():
f1 = plotting_function1()
ax1 = plt.gca()
ax1.remove()
f2 = plotting_function2()
ax2 = plt.gca()
ax1.figure = f2
f2.axes.append(ax1)
f2.add_axes(ax1)
# These positions are copied from a call to subplots().
ax1.set_position(Bbox([[0.125, 0.11], [0.477, 0.88]]))
ax2.set_position(Bbox([[0.55, 0.11], [0.9, 0.88]]))
plt.show()
main()

Showing subplots at each pass of a loop

I would essentially like to do the following:
import matplotlib.pyplot as plt
import numpy as np
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for i in range(10):
ax1.scatter(i, np.sqrt(i))
ax1.show() # something equivalent to this
ax2.scatter(i, i**2)
That is, each time a point is plotted on ax1, it is shown - ax2 being shown once.
You cannot show an axes alone. An axes is always part of a figure. For animations you would want to use an interactive backend. Then the code in a jupyter notebook could look like
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
frames = 10
x = np.arange(frames)
line1, = ax1.plot([],[], ls="", marker="o")
line2, = ax2.plot(x, x**2, ls="", marker="o")
ax2.set_visible(False)
def animate(i):
line1.set_data(x[:i], np.sqrt(x[:i]))
ax1.set_title(f"{i}")
ax1.relim()
ax1.autoscale_view()
if i==frames-1:
ax2.set_visible(True)
fig2.canvas.draw_idle()
ani = FuncAnimation(fig1, animate, frames=frames, repeat=False)
plt.show()
If you want to change plots dynamically I'd suggest you don't redraw the whole plot every time, this will result in very laggy behavior. Instead you could use Blit to do this. I used it in a previous project. Maybe it can help you too if you just take the parts from this you need:
Python project dynamically updating plot

Is there a restriction on catplot with subplot?

Seaborn's catplot does not seem to be able to work with plt.subplots(). Am not sure whats the issue here but i dont seem to be able to put them side by side.
#Graph 1
plt.subplot(121)
sns.catplot(x="HouseStyle",y="SalePrice",data=df,kind="swarm")
#Graph 2
plt.subplot(122)
sns.catplot(x="LandContour",y="SalePrice",data=df,kind="swarm")
Output:
Catplot is a figure-level function whereas you cannot use axes. Try using stripplot instead.
fig, axs = plt.subplots (1, 2, figsize=(25, 15))
sns.stripplot(x='category_col', y='y_col_1', data=df, ax=axs[0])
sns.stripplot(x='category_col', y='y_col_2', data=df, ax=axs[1])
You need to pass the created axis to seaborn's catplot while plotting. Following is a sample answer demonstrating this. A couple of things
I would suggest using add_subplot to create subplots like yours
The catplot will still return an axis object which can be closed using plt.close() where the number inside the brackets correspond to the figure count. See this answer for more details on close()
Complete reproducible answer
import seaborn as sns
import matplotlib.pyplot as plt
exercise = sns.load_dataset("exercise")
fig = plt.figure()
ax1 = fig.add_subplot(121)
g = sns.catplot(x="time", y="pulse", hue="kind", data=exercise, ax=ax1) # pass ax1
ax2 = fig.add_subplot(122)
g = sns.catplot(x="time", y="pulse", hue="kind", data=exercise, ax=ax2) # pass ax2
plt.close(2)
plt.close(3)
plt.tight_layout()
Thank you Sheldore for giving an idea of using close(). I tried this way and it worked.
_, ax = plt.subplots(2, 3, figsize=(20,10))
for n, feat in enumerate(cat_feats):
sns.catplot(x='feat', kind='count', data=df, ax=ax[n//3][n%3])
plt.close()

How to use ax with Pandas and Matplotlib

I have a very basic question. I am using a pandas dataframe to make this plot, but I want to add highlighting around certain dates.
In[122]:
df1_99.plot(x='date', y='units', ylim=[0,11], figsize=[12,12])
Out[122]:
I found this code on stackoverflow to add highlighting.
fig, ax = plt.subplots()
ax.plot_date(t, y, 'b-')
ax.axvspan(*mdates.datestr2num(['10/27/2011', '11/2/2011']), color='red', alpha=0.5)
fig.autofmt_xdate()
plt.show()
My question is how can I use ax.avxspan with my current code? Or do I need to convert my x='date', and y='units' to numpy arrays and use the format as in the code above?
pandas.DataFrame.plot will return the matplotlib AxesSubplot object.
ax = df1_99.plot(x='date', y='units', ylim=[0,11], figsize=[12,12])
ax.axvspan(*mdates.datestr2num(['10/27/2011', '11/2/2011']), color='red', alpha=0.5)
plt.show()
If you want to create an ax object in advance, you can pass it into plot as below
fig, ax = plt.subplots()
df1_99.plot(x='date', y='units', ylim=[0,11], figsize=[12,12], ax=ax)
ax.axvspan(*mdates.datestr2num(['10/27/2011', '11/2/2011']), color='red', alpha=0.5)
plt.show()
Finally, you can usually get the current figure and axes objects using the following functions
fig = plt.gcf()
ax = plt.gca()

Categories