I created two subplots on a MPL figure, but i'm having an hard time setting the size on them. I want the space to be splitted between the two charts, so each chart needs to have 50% of the total width of the figure, and i want them to have the same height of the figure, here is how i initialized the subplots:
fig = plt.figure(facecolor='#131722',dpi=155, figsize=(10, 3))
ax1 = plt.subplot2grid((3,3), (2,0), facecolor='#131722')
ax2 = plt.subplot2grid((5,3), (2,2), colspan=5, rowspan=4, facecolor='#131722')
Colors = [['#0400ff', '#FF0000'], ['#09ff00', '#ff8c00']]
for x in List:
Index = List.index(x)
rate_buy = []
total_buy = []
rate_sell = []
total_sell = []
for y in x['data']['asks']:
rate_sell.append(y[0])
total_sell.append(y[1])
for y in x['data']['bids']:
rate_buy.append(y[0])
total_buy.append(y[1])
rBuys = pd.DataFrame({'buy': rate_buy})
rSells = pd.DataFrame({'sell': rate_sell})
tBuys = pd.DataFrame({'total': total_buy})
tSells = pd.DataFrame({'total': total_sell})
ax1.plot(rBuys.buy, tBuys.total, color=Colors[Index][0], linewidth=0.5, alpha=1, label='test')
ax2.plot(rSells.sell, tSells.total, color=Colors[Index][1],alpha=0.5, linewidth=1, label=x['exchange'])
ax1.fill_between(rBuys.buy, 0, tBuys.total, facecolor=Colors[Index][0], alpha=0.4)
ax2.fill_between(rSells.sell, 0, tSells.total, facecolor=Colors[Index][1], alpha=0.4)
And this is what i'm getting:
use plt.tight_layout() before calling plt.show().
Related
Please I need help with a plot. I am making a 3x3 dimension figure containing 7 subplots. I want two(2) of the subplots (ax6 and ax7) to be stacked plots. Does anyone have an idea how I can make this work? I used the code below to make the grid.
fig = plt.figure()
fig.set_figheight(8)
fig.set_figwidth(10)
gs = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[0, -2])
ax3 = plt.subplot(gs[0, -1])
ax4 = plt.subplot(gs[1, 0])
ax5 = plt.subplot(gs[-1, 0])
ax6 = plt.subplot(gs[1:, -2])
ax7 = plt.subplot(gs[1:, -1])
I tried making the stacked plot for ax6 using the code below
ax6[0].plot(s[['xa']], s[['ac1']], label = "Data")
ax6[0].plot(s[['xa']], s[['ac2']], label = "C-C")
ax6[0].plot(s[['xa']], s[['ac3']], label = "C-O")
ax6[0].plot(s[['xa']], s[['ac4']], label = "C=C")
ax6[0].plot(s[['xa']], s[['ea1']], label = "Envelope")
ax6[0].text(0.08, 0.70, 'C', ha='center', va='baseline', wrap=True, fontsize= 10, fontweight='bold', color='darkgreen', transform=ax6[0].transAxes)
ax6[1].plot(s[['xb']], s[['bc1']], label = "Data")
ax6[1].plot(s[['xb']], s[['bc2']], label = "C-C")
ax6[1].plot(s[['xb']], s[['bc3']], label = "C-O")
ax6[1].plot(s[['xb']], s[['bc4']], label = "C=C")
ax6[1].plot(s[['xb']], s[['be1']], label = "Envelope")
ax6[1].text(0.08, 0.70, 'm.C', ha='center', va='baseline', wrap=True, fontsize= 10, fontweight='bold', color='darkgreen', transform=ax6[1].transAxes)
Please look at the comments in the code:
import matplotlib.pyplot as plt
from matplotlib import gridspec
import numpy as np
fig = plt.figure(figsize=(10, 8))
g = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(g[0, 0])
ax2 = plt.subplot(g[0, 1])
ax3 = plt.subplot(g[0, 2])
ax4 = plt.subplot(g[1, 0])
ax5 = plt.subplot(g[2, 0])
# Create another grid
g2 = gridspec.GridSpec(3, 3)
g2.update(hspace=0.00)
# Generate data for three subplots in g2
x = np.linspace(0, 2 * np.pi, 400)
ya = np.sin(x)
yb = np.cos(x)
y7 = np.sin(x) ** 2
# Get three different Axes objects
ax6a = plt.subplot(g2[1, 1])
ax6b = plt.subplot(g2[2, 1], sharex=ax6a)
ax7 = plt.subplot(g2[1:, -1])
# Hide the xticklabels of top subplot in the shared plots
plt.setp(ax6a.get_xticklabels(), visible=False)
# Set xticks for lower subplots in the shared plots
ax6b.set_xticks(np.pi * np.array([0, 1/2, 1, 3/2, 2]))
# Try plotting
ax6a.plot(x, ya)
ax6b.plot(x, yb, 'g')
ax7.plot(x, y7, 'r')
plt.tight_layout()
plt.show()
This gives:
This answer was motivated by this answer and examples from older documentation of matplotlib.
If you want ax7 (red color subplot here) represented in to two separate subplots, either create a new Gridspec or use g depending on attributes you want to assign them e.g. in the code above:
# ax7 = plt.subplot(g2[1:, -1])
# ax7.plot(x, y7, 'r')
ax7a = plt.subplot(g[1, 2])
ax7b = plt.subplot(g[2, 2])
ax7a.plot(x, y7, 'r')
ax7b.plot(x, y7, 'r')
This gives:
Currently I have a plot with too many points, I want to avoid overlapping. Want to know how to reduce the amount of points in order to have a smoother line.
Plot Code
fig = plt.figure(1, figsize = (18,10)) # Figure size in inches (size_x, size_y)
ax = plt.axes()
min_val = prediction_intervals2[:, 0]
max_val = prediction_intervals2[:, 1]
true_values = y_test
predicted_values = PLS_Model1.predict(X_test)
plt.plot(min_val, label = "Min", color='blue')
plt.plot(max_val, label = "Max", color='red')
plt.plot(true_values, label = "y", color = "black")
plt.plot(predicted_values, label = "y\u0302", marker='o')
plt.title('Conformal Predictor Final Predictions')
plt.legend()
plt.show()
Current Plot
Desired Plot
Plot that I want
I was able to revise my code properly and came to the desired output by just selecting less data points, quite simple. Posted the answer just in case.
min_val_normal = plot_normalized_table[['Min']]
max_val_normal = plot_normalized_table[['Max']]
original_normal = plot_normalized_table[['Original Label']]
interval_normal = plot_normalized_table[['Interval Size']]
normal_predicted = predicted_values[0:50]
fig = plt.figure(1, figsize = (18,10)) # Figure size in inches (size_x, size_y)
ax = plt.axes()
#predicted_values = PLS_Model1.predict(X_test) #Predictions from test data (run at least once for the plot to work)
plt.plot(min_val_normal, label = "Min", color='blue')
plt.plot(max_val_normal, label = "Max", color='red')
plt.plot(original_normal, label = "y", color = "black")
plt.plot(normal_predicted, label = "y\u0302", marker='o', )
plt.title('Normalized Final Conformal Predictions')
plt.xlim([-1, 51])
plt.ylim([-1, 2])
plt.legend()
plt.show()
I have a 2 dimensional time series plotted as FacetGrid via xarray.
p = gmt.plot.line(x='time', add_legend=False, alpha = 0.1, color = ('k'), ylim = (-1, 1.2), col='MCrun', col_wrap = 5)
I want to add another lineplot with the same axes and dimensions on top. For individual members that's simply:
gmt.isel(MCrun=0).plot.line(x='time', add_legend=False, alpha = 0.1, color = 'k', ylim = (-3, 1.2))
gmt_esmean.isel(MCrun=0).plot.line(x='time', add_legend=False, color = 'red')
But using the same with two facet grids results in 20 plots - 10 with the individual lines and 10 with the mean. The closest I've come is
def smean_plot(*args, **kwargs):
gmt_esmean.plot.line(x='time', add_legend=False, color = 'red')
p = gmt.plot.line(x='time', add_legend=False, alpha = 0.1, color = ('k'), ylim = (-1, 1.2), col='MCrun', col_wrap = 5)
p.map(smean_plot)
Which plot all means in all plots and adds unwanted axes titles.
Any ideas how to only add the mean to the corresponding ensemble are greatly appreciated.
Ok one approach I was happy with is to plot the figures one-by-one via subplot in a loop. Set x and y axes as shared and reduce figure margin. It's not as elegant as I would've hoped but works just fine.
fig, axs = plt.subplots(ncols=5, nrows=2, figsize=(18,6), sharex=True, sharey=True, gridspec_kw={'hspace': 0.2, 'wspace': 0.1})
axs = axs.ravel()
for i in range(10):
gmt.isel(MCrun=i).plot.line(ax = axs[i], x='time', add_legend=False, alpha = 0.1, color = ('k'), ylim = (-1.2, 0.8))
gmt_esmean.isel(MCrun=i).plot.line(ax = axs[i], x='time', add_legend=False, color = 'red')+ 1
plt.draw()
I'm creating a chart with matplotlib, here is my code:
fig = plt.figure(facecolor='#131722',dpi=155, figsize=(8, 4))
ax1 = plt.subplot2grid((1,2), (0,0), facecolor='#131722')
Colors = [['#0400ff', '#FF0000'], ['#09ff00', '#ff8c00']]
for x in List:
Index = List.index(x)
rate_buy = []
total_buy = []
for y in x['data']['bids']:
rate_buy.append(y[0])
total_buy.append(y[1])
rBuys = pd.DataFrame({'buy': rate_buy})
tBuys = pd.DataFrame({'total': total_buy})
ax1.plot(rBuys.buy, tBuys.total, color=Colors[Index][0], linewidth=0.5, alpha=0.8)
ax1.fill_between(rBuys.buy, 0, tBuys.total, facecolor=Colors[Index][0], alpha=1)
And here is the output:
The problem with the current output is that the colors of the two areas are "merging": basically the area BELOW the blue line should be blue, but instead it's green. How can i set it to be blue, for example, like in my example?
Example List data:
[[9665, 0.07062500000000001], [9666, 0.943708], [9667, 5.683787000000001], [9668, 9.802289], [9669, 11.763305], [9670, 14.286004], [9671, 16.180122], [9672, 23.316723000000003], [9673, 30.915156000000003], [9674, 33.44226200000001], [9675, 36.14526200000001], [9676, 45.76024100000001], [9677, 51.85294700000001], [9678, 58.79529300000001], [9679, 59.05322900000001], [9680, 60.27704500000001], [9681, 60.743885000000006], [9682, 66.75103700000001], [9683, 71.86412600000001], [9684, 73.659636], [9685, 78.08502800000001], [9686, 78.19614200000001], [9687, 79.98396400000001], [9688, 90.55855800000002]]
I guess the hint of #JohanC is correct, you are plotting in the wrong order and overlay your previous plots with new ones.
I tried to recreate a small example where total_buy1 > total_buy0, so in order to get the desired result you first have to plot total_buy1
and then total_buy0:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
Colors = [['#0400ff', '#FF0000'],
['#09ff00', '#ff8c00']]
n = 100
rate_buy = np.linspace(0, 1000, 100)
total_buy0 = np.linspace(0, 300, n)[::-1] + np.random.normal(scale=10, size=n)
total_buy1 = np.linspace(0, 600, n)[::-1] + np.random.normal(scale=10, size=n)
ax.plot(rate_buy, total_buy1, color=Colors[1][1], linewidth=0.5, alpha=0.8)
ax.fill_between(rate_buy, 0, total_buy1, facecolor=Colors[1][0], alpha=1)
ax.plot(rate_buy, total_buy0, color=Colors[0][1], linewidth=0.5, alpha=0.8)
ax.fill_between(rate_buy, 0, total_buy0, facecolor=Colors[0][0], alpha=1)
I noticed that you use Colors[Index][0] for both plotting calls, so the line and the area will not have different colors.
After moving all of my 'y' axes to subplots I get an unwanted axis. It's the black one on the left. Does anyone know how to get rid of it? I'm sure it's getting plotted when I call the figure, however I'm not sure how to get rid of it.
def mpl_plot(self, plot_page, replot = 0): #Data stored in lists
if plot_page == 1: #Plot 1st Page
#plt0 = self.mplwidget.axes
fig = self.mplwidget.figure #Add a figure
if plot_page == 2: #Plot 2nd Page
#plt0 = self.mplwidget_2.axes
fig = self.mplwidget_2.figure #Add a figure
if plot_page == 3: #Plot 3rd Page
#plt0 = self.mplwidget_3.axes
fig = self.mplwidget_3.figure #Add a figure
#Clears Figure if data is roplotted
if replot == 1:
fig.clf()
par0 = fig.add_subplot(111)
par1 = fig.add_subplot(111)
par2 = fig.add_subplot(111)
#Add Axes
plt = par0.twinx()
ax1 = par1.twinx()
ax2 = par2.twinx()
impeller = str(self.comboBox_impellers.currentText()) #Get Impeller
fac_curves = self.mpl_factory_specs(impeller)
fac_lift = fac_curves[0]
fac_power = fac_curves[1]
fac_flow = fac_curves[2]
fac_eff = fac_curves[3]
fac_max_eff = fac_curves[4]
fac_max_eff_bpd = fac_curves[5]
fac_ranges = self.mpl_factory_ranges()
min_range = fac_ranges[0]
max_range = fac_ranges[1]
#Plot Chart
plt.hold(True)
plt.plot(fac_flow, fac_lift, 'b', linestyle = "dashed", linewidth = 1)
ax1.plot(fac_flow, fac_power, 'r', linestyle = "dashed", linewidth = 1)
ax2.plot(fac_flow, fac_eff, 'g', linestyle = "dashed", linewidth = 1)
#Move spines
ax2.spines["right"].set_position(("outward", 25))
self.make_patch_spines_invisible(ax2)
ax2.spines["right"].set_visible(True)
#Plot x axis minor tick marks
minorLocatorx = AutoMinorLocator()
ax1.xaxis.set_minor_locator(minorLocatorx)
ax1.tick_params(which='both', width= 0.5)
ax1.tick_params(which='major', length=7)
ax1.tick_params(which='minor', length=4, color='k')
#Plot y axis minor tick marks
minorLocatory = AutoMinorLocator()
plt.yaxis.set_minor_locator(minorLocatory)
plt.tick_params(which='both', width= 0.5)
plt.tick_params(which='major', length=7)
plt.tick_params(which='minor', length=4, color='k')
#Make Border of Chart White
fig.set_facecolor('white')
#Plot Grid
plt.grid(b=True, which='both', color='k', linestyle='-')
#set shaded Area
plt.axvspan(min_range, max_range, facecolor='#9BE2FA', alpha=0.5) #Yellow rectangular shaded area
#Set Vertical Lines
plt.axvline(fac_max_eff_bpd, color = '#69767A')
#BEP MARKER *** Can change marker style if needed
bep = fac_max_eff * 0.90 #bep is 90% of maximum efficiency point
bep_corrected = bep * 0.90 # We knock off another 10% to place the arrow correctly on chart
ax2.annotate('BEP', xy=(fac_max_eff_bpd, bep_corrected), xycoords='data', #Subtract 2.5 shows up correctly on chart
xytext=(-50, 30), textcoords='offset points',
bbox=dict(boxstyle="round", fc="0.8"),
arrowprops=dict(arrowstyle="-|>",
shrinkA=0, shrinkB=10,
connectionstyle="angle,angleA=0,angleB=90,rad=10"),
)
#Set Scales
plt.set_ylim(0,max(fac_lift) + (max(fac_lift) * 0.40)) #Pressure
#plt.set_xlim(0,max(fac_flow))
ax1.set_ylim(0,max(fac_power) + (max(fac_power) * 0.40)) #Power
ax2.set_ylim(0,max(fac_eff) + (max(fac_eff) * 0.40)) #Effiency
plt.yaxis.tick_left()
# Set Axes Colors
plt.tick_params(axis='y', colors='b')
ax1.tick_params(axis='y', colors='r')
ax2.tick_params(axis='y', colors='g')
# Set Chart Labels
plt.yaxis.set_label_position("left")
plt.set_xlabel("BPD")
plt.set_ylabel("Feet" , color = 'b')
#ax1.set_ylabel("BHP", color = 'r')
#ax1.set_ylabel("Effiency", color = 'g')
# Set tight layout
fig.set_tight_layout
# Since we moved Feet Axis to subplot, extra unneeded axis was created. This Removes it
# Refresh
fig.canvas.update()
fig.canvas.draw()
Well it looks like you have three y-axes, referencing the one you want to not be shown, you could try adding:
ax.yaxis.set_tick_params(labelsize=0, length=0, which='major')
to just make invisible the labels and ticks. I think it's ax2 you want gone?