I'm attempting to create two separate plots as subplots, on the same figure. Both plots are polar. My attempts cause them to plot on the same graph.
def GenerateTrigonometryTable(x): #Define Function
A = np.arange (0,360,x)
B = np.sin(A*np.pi/180)
C = np.cos(A*np.pi/180)
table = np.dstack(([A],[B],[C]))
return table
Theta = (GenerateTrigonometryTable(5)[:,:,0])
STheta = (GenerateTrigonometryTable(5)[:,:,1])
CTheta = (GenerateTrigonometryTable(5)[:,:,2])
ax1 = plt.subplot(111, projection='polar')
ax1.plot(Theta.flatten(), STheta.flatten())
ax2 = plt.subplot(111, projection='polar')
ax2.plot(Theta.flatten(), CTheta.flatten())
fig.show()
This plots it on the same graph and I need it to be a figure of two separate graphs.
You need the following: 121 means first plot on a 1x2 subplots grid and 122 means second plot on that 1x2 subplots grid.
ax1 = plt.subplot(121, projection='polar')
ax1.plot(Theta.flatten(), STheta.flatten())
ax2 = plt.subplot(122, projection='polar')
ax2.plot(Theta.flatten(), CTheta.flatten())
fig.show()
A more object-oriented approach would be :
fig = plt.figure()
ax1 = fig.add_subplot(121, projection='polar')
ax2 = fig.add_subplot(122, projection='polar')
ax1.plot(Theta.flatten(), STheta.flatten())
ax2.plot(Theta.flatten(), CTheta.flatten())
fig.show()
Equivalent of Sheldore's answer but shows how figures, axes and plots are articulated in matplotlib.
Related
I am creating two plots using matplotlib, each of them is a subplot showing two metrics on the same axis.
I'm trying to run them so they show as two charts but in one graphic, so that when I save the graphic I see both plots. At the moment, running the second plot overwrites the first in memory so I can only ever save the second.
How can I plot them together?
My code is below.
plot1 = plt.figure()
fig,ax1 = plt.subplots()
ax1.plot(dfSat['time'],dfSat['wind_at_altitude'], 'b-', label = "speed", linewidth = 5.0)
plt.title('Wind Speeds - Saturday - {}'.format(windloc))
plt.xlabel('Time of day')
plt.ylabel('Wind speed (mph)')
ax1.plot(dfSat['time'],dfSat['gust_at_altitude'], 'r-', label = "gust", linewidth = 5.0)
plt.legend(loc="upper right")
ax1.text(0.05, 0.95, calcmeassat, transform=ax1.transAxes, fontsize=30,
verticalalignment='top')
plt.ylim((0,100))
plot2 = plt.figure()
fig,ax2 = plt.subplots()
ax2.plot(dfSun['time'],dfSun['wind_at_altitude'], 'b-', label = "speed", linewidth = 5.0)
plt.title('Wind Speeds - Sunday - {}'.format(windloc))
plt.xlabel('Time of day')
plt.ylabel('Wind speed (mph)')
ax2.plot(dfSun['time'],dfSun['gust_at_altitude'], 'r-', label = "gust", linewidth = 5.0)
plt.legend(loc="upper right")
ax2.text(0.05, 0.95, calcmeassun, transform=ax2.transAxes, fontsize=30,
verticalalignment='top')
plt.ylim((0,100))
As mentioned, in your case you only need one level of subplots, e.g., nrows=1, ncols=2.
However, in matplotlib 3.4+ there is such a thing as "subplotting subplots" called subfigures, which makes it easier to implement nested layouts, e.g.:
How to create row titles for subplots
How to share colorbars within some subplots
How to share xlabels within some subplots
Subplots
For your simpler use case, create 1x2 subplots with ax1 on the left and ax2 on the right:
# create 1x2 subplots
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(16, 4))
# plot saturdays on the left
dfSat.plot(ax=ax1, x='date', y='temp_min')
dfSat.plot(ax=ax1, x='date', y='temp_max')
ax1.set_ylim(-20, 50)
ax1.set_title('Saturdays')
# plot sundays on the right
dfSun.plot(ax=ax2, x='date', y='temp_min')
dfSun.plot(ax=ax2, x='date', y='temp_max')
ax2.set_ylim(-20, 50)
ax2.set_title('Sundays')
Subfigures
Say you want something more complicated like having the left side show 2012 with its own suptitle and right side to show 2015 with its own suptitle.
Create 1x2 subfigures (left subfig_l and right subfig_r) with 2x1 subplots on the left (top ax_lt and bottom ax_lb) and 2x1 subplots on the right (top ax_rt and bottom ax_rb):
# create 1x2 subfigures
fig = plt.figure(constrained_layout=True, figsize=(12, 5))
(subfig_l, subfig_r) = fig.subfigures(nrows=1, ncols=2, wspace=0.07)
# create top/box axes in left subfig
(ax_lt, ax_lb) = subfig_l.subplots(nrows=2, ncols=1)
# plot 2012 saturdays on left-top axes
dfSat12 = dfSat.loc[dfSat['date'].dt.year.eq(2012)]
dfSat12.plot(ax=ax_lt, x='date', y='temp_min')
dfSat12.plot(ax=ax_lt, x='date', y='temp_max')
ax_lt.set_ylim(-20, 50)
ax_lt.set_ylabel('Saturdays')
# plot 2012 sundays on left-top axes
dfSun12 = dfSun.loc[dfSun['date'].dt.year.eq(2012)]
dfSun12.plot(ax=ax_lb, x='date', y='temp_min')
dfSun12.plot(ax=ax_lb, x='date', y='temp_max')
ax_lb.set_ylim(-20, 50)
ax_lb.set_ylabel('Sundays')
# set suptitle for left subfig
subfig_l.suptitle('2012', size='x-large', weight='bold')
# create top/box axes in right subfig
(ax_rt, ax_rb) = subfig_r.subplots(nrows=2, ncols=1)
# plot 2015 saturdays on left-top axes
dfSat15 = dfSat.loc[dfSat['date'].dt.year.eq(2015)]
dfSat15.plot(ax=ax_rt, x='date', y='temp_min')
dfSat15.plot(ax=ax_rt, x='date', y='temp_max')
ax_rt.set_ylim(-20, 50)
ax_rt.set_ylabel('Saturdays')
# plot 2015 sundays on left-top axes
dfSun15 = dfSun.loc[dfSun['date'].dt.year.eq(2015)]
dfSun15.plot(ax=ax_rb, x='date', y='temp_min')
dfSun15.plot(ax=ax_rb, x='date', y='temp_max')
ax_rb.set_ylim(-20, 50)
ax_rb.set_ylabel('Sundays')
# set suptitle for right subfig
subfig_r.suptitle('2015', size='x-large', weight='bold')
Sample data for reference:
import pandas as pd
from vega_datasets import data
df = data.seattle_weather()
df['date'] = pd.to_datetime(df['date'])
dfSat = df.loc[df['date'].dt.weekday.eq(5)]
dfSun = df.loc[df['date'].dt.weekday.eq(6)]
It doesn't work like that. Subplots are what they are called; plots inside a main plot.
That means if you need two subplots; then you need one plot containing two subplots in it.
# figure object NOT plot object
# useful when you want only one plot NO subplots
fig = plt.figure()
# 2 subplots inside 1 plot
# 1 row, 2 columns
fig, [ax1, ax2] = plt.subplots(1, 2)
# then call plotting method on each axis object to
# create plot on that subplot
sns.histplot(...., ax=ax1)
sns.violinplot(..., ax=ax2)
# or using matplotlib like this
ax1.plot()
ax2.plot()
Learn more about subplots
fig = plt.figure()
ax = fig.add_subplot(111)
scatter = ax.scatter(wh1['area'],wh1['rain'],
c=kmeans[0],s=50)
ax.set_title('K-Means Clustering')
ax.set_xlabel('area')
ax.set_ylabel('rain')
plt.colorbar(scatter)
fig = plt.figure()
ax1 = fig.add_subplot(111)
scatter = ax.scatter(wh1['area'],wh1['wind'],
c=kmeans[0],s=50)
ax1.set_title('K-Means Clustering')
ax1.set_xlabel('area')
ax1.set_ylabel('wind')
plt.colorbar(scatter)
plot.show()
this code creates two separate plots, i want to create one plot that contains both of these.i left an image of how the plots appear. Help would be appreciated, thanks
a suggested solution was to avoid plotting twice and using subplots instead, but this causes the 2 graphs to bisect each other any suggested fixes?
fig = plt.figure()
ax = fig.add_subplot(121)
scatter = ax.scatter(wh1['area'],wh1['rain'],
c=kmeans[0],s=50)
ax.set_title('K-Means Clustering')
ax.set_xlabel('area')
ax.set_ylabel('rain')
plt.colorbar(scatter)
ax1 = fig.add_subplot(122)
scatter = ax.scatter(wh1['area'],wh1['wind'],
c=kmeans[0],s=50)
ax1.set_title('K-Means Clustering')
ax1.set_xlabel('area')
ax1.set_ylabel('wind')
plt.colorbar(scatter)
You can use subplots. Instead of making different figures you can call add_subplot on the same figure.
You make a figure by the following code and get a handle to a figure:
fig = plt.figure()
Then you determine the number of rows and columns of plots inside that figure by a number that you pass to the add_subplot function. For example, if you want a layout of one row and two columns the first two digits in the argument is 12 and the third digit determines which cell:
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
So, your code will be like this:
fig = plt.figure()
ax = fig.add_subplot(121)
scatter = ax.scatter(wh1['area'],wh1['rain'],
c=kmeans[0],s=50)
ax.set_title('K-Means Clustering')
ax.set_xlabel('area')
ax.set_ylabel('rain')
plt.colorbar(scatter)
ax1 = fig.add_subplot(122)
scatter = ax1.scatter(wh1['area'],wh1['wind'],
c=kmeans[0],s=50)
ax1.set_title('K-Means Clustering')
ax1.set_xlabel('area')
ax1.set_ylabel('wind')
plt.colorbar(scatter)
plot.show()
Here's my code so far:
QE_ellip_fixed = [-1.04e-3,-1.04e-2,-0.1,-0.76,-2.34,-2.54]
QL_ellip_fixed = [1.77e-4,9.89e-4,-6e-2,-2.9,-4.45,-2.74]
QP_ellip_fixed = [1.26e-3,1.45e-2,0.14,0.98,2.6,2.5]
QE_ellip_varied = [-1.73e-4,-1.73e-3,-1.71e-2,-0.15,-0.86,-3.16]
QL_ellip_varied = [7.57e-5,7.53e-4,5.4e-3,-0.13,-4.15,-7.3]
QP_ellip_varied = [1.41e-3,1.77e-3,2.34e-2,0.22,1.33,3.14]
RHScalls_ellip = [764021,76388,7625,750,63,3]
RHScalls_circ = [629171,62864,6234,577,41,5]
QE_circ_fixed= [-1.26e-4,-1.26e-3,-1.24e-2,-0.11,-0.57,-2.98]
QL_circ_fixed = [-1.32e-4,5.89e-4,1.5e-3,-0.51,0.4,-9.57]
QP_circ_fixed = [1.45e-2,9.25e-3,4.62e-2,0.58,3.5,8.54]
QE_circ_varied = [-1.26e-4,-1.25e-3,-1.24e-2,-0.11,-0.56,-2.13]
QL_circ_varied = [-1.33e-4,5.88e-4,1.69e-3,-0.45,-0.64,-6.58]
QP_circ_varied = [1.45e-2,9.32e-3,5.2e-2,0.55,3.11,13.05]
alp = [1e-5,1e-4,1e-3,1e-2,1e-1,1]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(alp,np.abs(QE_ellip_varied),label='$|Q_E|$')
ax1.plot(alp,np.abs(QL_ellip_varied),label='$|Q_L|$')
ax1.plot(alp,np.abs(QP_ellip_varied),label='$|Q_P|$')
ax2 = ax1.twiny()
ax2.set_xticks([1e-5,1e-4,1e-3,1e-2,1e-1,1])
ax2.set_xticklabels(RHScalls_ellip)
ax1.set_xscale('log')
plt.yscale('log')
ax1.grid()
ax1.set_xlabel('alpha')
ax1.set_ylabel('Score (unitless)')
ax1.legend()
plt.show()
And here's the outputted image:
I want to have the values on the top axis have ticklabels in line with the grid lines already imposed, as they actually correspond to those gridlines, but I can't seem to make the top axis not behave in this annoying logarithmic way. I've only specified for axis 1 to have a logarithmic scale, but it seems to have applied to axis 2 as well...
it's because the axes share the y-axis, but not the x-axis. The xlimits are different for each..the following worked for me:
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()
ax1.set_xscale('log')
ax2.set_xscale('log') #make sure both log
plt.yscale('log')
ax1.plot(alp,np.abs(QE_ellip_varied),label='$|Q_E|$')
ax1.plot(alp,np.abs(QL_ellip_varied),label='$|Q_L|$')
ax1.plot(alp,np.abs(QP_ellip_varied),label='$|Q_P|$')
ax2.set_xlim(ax1.get_xlim()) #make sure same limits
ax2.set_xticks([1e-5,1e-4,1e-3,1e-2,1e-1,1])
ax2.set_xticklabels(RHScalls_ellip)
ax1.grid()
ax1.set_xlabel('alpha')
ax1.set_ylabel('Score (unitless)')
ax1.legend()
I cannot solve my problem. I am using matplotlib and I am plotting histogram and theoretical pdf, but I am not able to set the 0 values on both y-axes on the same level.
This is my code and the plot I get:
fig, ax1 = plt.subplots()
ax1.plot(x, pdf_g, label="Norm")
ax2 = ax1.twinx()
ax2.hist(df['col'])
plt.show()
I would like to have 2 histograms to appear on the same plot (with different colors, and possibly differente alphas). I tried
import random
x = pd.DataFrame([random.gauss(3,1) for _ in range(400)])
y = pd.DataFrame([random.gauss(4,2) for _ in range(400)])
x.hist( alpha=0.5, label='x')
y.hist(alpha=0.5, label='y')
x.plot(kind='kde', style='k--')
y.plot(kind='kde', style='k--')
plt.legend(loc='upper right')
plt.show()
This produces the result in 4 different plots. How can I have them on the same one?
If I understood correctly, both hists should go into the same subplot. So it should be
fig = plt.figure()
ax = fig.add_subplot(111)
_ = ax.hist(x.values)
_ = ax.hist(y.values, color='red', alpha=.3)
You can also pass the pandas plot method an axis object, so if you want both kde's in another plot do:
fig = plt.figure()
ax = fig.add_subplot(111)
x.plot(kind='kde', ax=ax)
y.plot(kind='kde', ax=ax, color='red')
To get everything into a single plot you need two different y-scales since kde is density and histogram is frequency. For that you use the axes.twinx() command.
fig = plt.figure()
ax = fig.add_subplot(111)
_ = ax.hist(x.values)
_ = ax.hist(y.values, color='red', alpha=.3)
ax1 = ax.twinx()
x.plot(kind='kde', ax=ax1)
y.plot(kind='kde', ax=ax1, color='red')
You can use plt.figure() and the function add_subplot(): the first 2 arguments are the number of rows and cols you want in your plot, the last is the position of the subplot in the plot.
fig = plt.figure()
subplot = fig.add_subplot(1, 2, 1)
subplot.hist(x.ix[:,0], alpha=0.5)
subplot = fig.add_subplot(1, 2, 2)
subplot.hist(y.ix[:,0], alpha=0.5)