This question already has an answer here:
Matplotlib: Colour multiple twinx() axes
(1 answer)
Closed 3 years ago.
I'm using the ax2 = ax1.twinx() attribute to have several graphs(3) with different scaling in the same plot, unfortunately, the values of the y-axis "run on top of each other" as shown here (right y axis, the blue values are sometimes hidden)
Here is the code for the graphs for reference
fig, ax1 = plt.subplots()
mpl.rcParams['lines.linewidth'] = 0.4
SMOOTH_FAC = 0.85
color = 'tab:red'
ax1.set_xlabel('Iterations')
ax1.set_ylabel('Non metric loss', color=color)
ax1.plot(smooth(net_loss,SMOOTH_FAC), color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('Metric supervised loss', color=color) # we already handled the x-label with ax1
ax2.plot(smooth(metric_super_loss,SMOOTH_FAC), color=color)
ax2.tick_params(axis='y', labelcolor=color)
ax3 = ax1.twinx()
color = 'tab:orange'
ax3.set_ylabel('Supervised loss', color=color,labelpad=20) # we already handled the x-label with ax1
ax3.plot(smooth(supervised_loss,SMOOTH_FAC),color=color, zorder=1)
ax3.tick_params(axis='y', labelcolor=color)
ax1.set_zorder(ax2.get_zorder()+ax3.get_zorder()+1)
ax1.patch.set_visible(False)
fig.tight_layout()
you can use get_yaxis().set_ticks() for each axes and set the tick to a blank list []
ax1.get_yaxis().set_ticks([])
ax2.get_yaxis().set_ticks([])
ax2.get_yaxis().set_ticks([])
or you can use the set_yticklabels() function to set tick for each axes.
ax1.set_yticklabels([])
ax2.set_yticklabels([])
ax3.set_yticklabels([])
or you can add left=False, right=False, labelleft=False, labelright=False params to your tick_params() for each axes
ax1.tick_params(axis='y', labelcolor=color,left=False, right=False,labelleft=False, labelright=False)
first one is cleaner.
Related
I tried to find this answer on the forum but I could not. I have made most of my plots with a grid, but this time it is easier to see what I want without a grid. However, the x-ticks disappeared while the y-ticks are still visible.
I have tried to make a minimum example below.
I have these as general for my plots
# Setting global font size for plots
small_size = 12
medium_size = 14
large_size = 16
plt.rc('axes', titlesize=large_size) # fontsize of the axes title
plt.rc('axes', labelsize=large_size) # fontsize of the x and y labels
plt.rc('xtick', labelsize=medium_size) # fontsize of the tick labels
plt.rc('ytick', labelsize=medium_size) # fontsize of the tick labels
plt.rc('legend',fontsize=medium_size) # fontsize of the legend
The plot below is mostly made by this script
fig, ax = plt.subplots(nrows=2, figsize=(13,7), sharex=True)
ax_y = ax[0].twinx()
ax_y.plot(df60.index, df60['sta'], color='magenta', label='STA') # linestyle = (0,(5, 10))
ax_y.plot(df60.index, df60['lta'], color='dodgerblue', label='LTA' )
ax[0].plot(df60.index, df60['displacement_butterfilt']-df60['displacement_butterfilt'][0], color='black', label='Displacement')
ax_2y = ax[1].twinx()
ax_2y.plot(df60.index, df60['sta'], color='magenta', label='STA') # linestyle = (0,(5, 10))
ax_2y.plot(df60.index, df60['lta'], color='dodgerblue', label='LTA' )
ax[1].plot(df60.index, df60['displacement_butterfilt']-df60['displacement_butterfilt'][0], color='black', label='Displacement')
# remove grid
ax[0].grid(False)
ax_y.grid(False)
ax[1].grid(False)
ax_2y.grid(False)
# start from 0 and remove space on each side of x-axis
ax[0].set_ylim(0, max(ax[0].get_ylim()))
ax[1].set_ylim(0, max(ax[0].get_ylim()))
ax[0].set_xlim(df60.index[0],df60.index[-1])
ax[1].set_xlim(df60.index[0],df60.index[-1])
fig.tight_layout()
plt.show()
Image of my problem
I have a time-series dataset. I want to plot the data i.e. current, voltage, and power each on the y-axis. I tried to do it with the following code but facing some errors (Image link attached).
Need help with the following:
adjusting scale of each y-axis
setting color of each y-axis
setting legends
Any other suggestions for improvement of code or alternative solutions are most welcome.
fig, ax1 = plt.subplots(figsize=(12,10))
ax2 = ax1.twinx()
ax3 = ax1.twinx()
ax1.set_ylim(0, 10)
ax2.set_ylim(0, 100)
ax3.set_ylim(0, 1000)
ax1.set_ylabel("Output Current")
ax2.set_ylabel("Output Voltage")
ax3.set_ylabel("Output Power")
color1 = plt.cm.viridis(0)
color2 = plt.cm.viridis(0.5)
color3 = plt.cm.viridis(.9)
ax1 = output_params.Output_Voltage.plot(color=color1, label= 'Output Current')
ax2 = output_params.Output_Current.plot(color=color2, label='Output Voltage')
ax3 = output_params.Output_Power.plot(color=color3, label='Output Power')
lns = [ax1, ax2, ax3]
ax1.legend(handles=lns, loc='best')
# right, left, top, bottom
ax3.spines['right'].set_position(('outward', 60))
ax1.yaxis.label.set_color(ax1.get_color())
ax2.yaxis.label.set_color(ax2.get_color())
ax3.yaxis.label.set_color(ax3.get_color())
# Adjust spacings w.r.t. figsize
fig.tight_layout()
I am trying to plot different pandas columns on two different scales, I took the example from the documentation but I am unsure about the error message. Here is my piece of code:
# Create some mock data
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('Liquidity')
ax1.set_ylabel('Price', color=color)
ax1.plot(orderbooks_hedged['topBid'], color=color)
ax1.plot(orderbooks_hedged['topAsk'], color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax2 = ax1.twinx()
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
ax2.plot(t, data2, color=color)
ax2.plot(orderbooks_hedged['topBidliquidity'], color=color)
ax2.plot(orderbooks_hedged['topAskliquidity'], color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()
And my two different dataframe columns looks like the following:
topBid topAsk topBidliquidity topAskliquidity
ts
2020-06-15 09:00:07 4.145097 4.170428 24.715769 35039.309622
2020-06-15 09:00:08 4.145097 4.170428 4944.701928 35039.309622
2020-06-15 09:00:09 4.144620 4.170428 4944.701928 35039.309622
2020-06-15 09:00:10 4.144620 4.170428 4944.701928 35039.309622
And the error is the following:
ValueError: view limit minimum -36879.560332175926 is less than 1 and is an invalid Matplotlib date value
I tried to google it a bit but I did not had one specific answer for my issue. Can someone help me to understand my issue? thanks!
fig, ax1 = plt.subplots()
plt.figure(figsize=[15,10])
color_ask = 'tab:red'
color_bid = 'tab:blue'
ax1.set_xlabel('Liquidity')
ax1.set_ylabel('Price')
ax1.plot(orderbooks_hedged.index, orderbooks_hedged['topBid'], color=color_bid)
ax1.plot(orderbooks_hedged.index, orderbooks_hedged['topAsk'], color=color_ask)
ax1.tick_params(axis='y')
ax2 = ax1.twinx()
ax2.set_ylabel('liquidity') # we already handled the x-label with ax1
ax2.plot(orderbooks_hedged.index, orderbooks_hedged['topBidliquidity'], color=color_bid)
ax2.plot(orderbooks_hedged.index, orderbooks_hedged['topAskliquidity'], color=color_ask)
ax2.tick_params(axis='y')
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()`enter code here`
I have two plots that I generated from my data:
Here the second plot shows the distribution of results from the first one.
What I want is to plot them side-by-side so you could see both the data and the distribution on the same plot. And I want plots to share y-axis as well.
I tried to do the following:
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(40, 15), sharey=True)
ax1 = sns.lineplot(plotting_df.index, plotting_df.error, color=('#e65400'), lw=2, label='random forest residual error')
ax1 = sns.lineplot(plotting_df.index, plotting_df.val, color=('#9b9b9b'), lw=1, label='current model residual error')
ax1 = sns.lineplot(plotting_df.index, 0, color=('#2293e3'), lw=1)
ax1.xaxis.set_visible(False)
ax1.set_ylabel('Residual Fe bias', fontsize=16)
ax1.set_title('Models residual error comparison', fontsize=20, fontweight='bold')
sns.despine(ax=ax1, top=True, bottom=True, right=True)
ax2 = sns.distplot(results_df.error, hist=True, color=('#e65400'), bins=81,
label='Random forest model', vertical=True)
ax2 = sns.distplot(plotting_df.val, hist=True, color=('#9b9b9b'),
bins=81, label='Rolling averages model', vertical=True)
ax2.set_title('Error distribution comparison between models', fontsize=20, fontweight='bold')
sns.despine(ax=ax2, top=True, right=True)
fig.savefig("blabla.png", format='png')
But when I do run it I get strange results - the first chart is in the second column, whereas I wanted it on the left and the second chart is completely blank. Not sure what I did wrong here.
Both lineplot and distplot accept a matplotlib axes object as an argument, which tells it which axes to plot onto. If no axes is passed into it, then the plot is placed onto the current axes.
You create a figure and 2 axes using :
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(40, 15), sharey=True)
Therefore, ax2 will be the current axes. So your distplot is being plotted on top of your lineplot, both in ax2.
You need to pass the axes into the seaborn plotting functions.
sns.lineplot(..., ax=ax1)
sns.distplot(..., ax=ax2)
I have the following code that makes four subplots in one figure:
f = figure( figsize=(7,7) )
f.add_axes([0.2,0.175,0.75,0.75])
f.subplots_adjust(left=0.15)
f.clf()
ax = f.add_subplot(111)
ax1 = f.add_subplot(221)
ax2 = f.add_subplot(222)
ax3 = f.add_subplot(223)
ax4 = f.add_subplot(224)
ax.xaxis.set_major_formatter( NullFormatter() )
ax.yaxis.set_major_formatter( NullFormatter() )
ax2.xaxis.set_major_formatter( NullFormatter() )
ax2.yaxis.set_major_formatter( NullFormatter() )
ax1.xaxis.set_major_formatter( NullFormatter() )
ax4.yaxis.set_major_formatter( NullFormatter() )
f.subplots_adjust(wspace=0,hspace=0)
ax1.plot(tbins[0:24], mean_yszth1, color='r', label='mean', marker='.', lw=3)
ax2.plot(tbins[0:24], mean_ysz1, color='r', label='mean', marker='.', lw=3)
ax3.plot(tbins[0:24], mean_yszth2, color='r', label='mean', marker='.', lw=3)
ax4.plot(tbins[0:24], mean_ysz2, color='r', label='mean', marker='.', lw=3)
ax1.set_xlim(0,12)
ax1.set_ylim(-0.5,0.5)
ax2.set_xlim(0,12)
ax2.set_ylim(-0.5,0.5)
ax3.set_xlim(0,12)
ax3.set_ylim(-0.5,0.5)
ax4.set_xlim(0,12)
ax4.set_ylim(-0.5,0.5)
ax.set_xlabel(r"$\mathrm{Time\ since\ last\ merger\ (Gyr)}$")
ax.set_ylabel(r"$\mathrm{\Delta Y_{SZ}/Y_{SZ}}$")
The result looks like this:
As you can see, the axis labels overlap with the ticks. I would like to move the common axis labels away from the axes a little. I can't figure out how best to do this.
Use labelpad parameter of set_ylabel and set_xlabel methods:
Definition: ax.set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs)
Docstring:
Call signature::
set_ylabel(ylabel, fontdict=None, labelpad=None, **kwargs)
Set the label for the yaxis
*labelpad* is the spacing in points between the label and the y-axis
This is what I get with labelpad set to 50 (x) and 60 (y). I had to modify manually figure margins as the labels were outside the figure frame when using the default configuration.
Edit
From your comments it seems you could be using a very old version of matplotlib. Labelpad parameter has been in matplotlib from many versions ago but the way to of setting it could be different (I do not know for sure).
In the web I found some comments that point to this usage:
ax.xaxis.LABELPAD = 8 # default is 5
also I have seen it like:
ax.xaxis.labelpad = 8