I've got two pandas series I would like to plot on the same axis, using a twinx. Here is a picture of what it looks like:
fig,(ax1,ax2,ax3,ax4,ax5) = plt.subplots(nrows = 5,ncols = 1, figsize = (8,13))
plt.subplots_adjust(hspace = 0.5)
ax1_1 = ax1.twinx()
df[["Var"]].plot(ax = ax1, label = 'Variance')
df[['w2']].plot(ax = ax1_1, color = 'g', label = '$w$')
ax1.locator_params('y',nbins = 5)
ax1_1.locator_params('y', nbins = 5)
ax1.set_ylabel('AC', labelpad = 10)
ax1_1.set_ylabel('w', labelpad = 10)
ax1.legend(loc = 'upper left')
ax1_1.legend()
I'd like to edit the x axis ticks, but using ax1.set_xticks() and ax1.set_xticklabels() doesn't seem to work. Furthermore, why are there are no x ticks after I execute the code found above? Shouldn't the ticks be the index of the Series?
Related
I'm having trouble with a plot I'm trying to make in matplotlib. I'm including the current version below (note the partially visible legend in the top right). I have two questions:
How do I get all of the subplots to shrink inward (i.e. their right boundaries to move leftward) to make room for the legend?
I would like group these axes into pairs by adding vertical space between each pair, i.e. if we are counting axes from 0 then I would like to have extra space between axes 1 and 2 as well as between 3 and 4. It seems like there should be a way to do this using subfigures or nested gridspecs, but subplots was the only way I could see to implement a shared x axis.
Thanks in advance.
Here is the code that I am using to generate it:
fig, axs = plt.subplots(6, 1, sharex = True, figsize = (8,8))
ts = [9, 38, 47]
for i in range(len(ts)):
t = ts[i]
ax = axs[2*i]
twin = axs[2*i+1]
bed_profile = dye_test.bed_profile_vs_t[t]
head_top_BC = head_top_BC_vs_t[t]
x_interp = np.linspace(x_axis.min(), x_axis.max(), 1000)
head_fn = interp1d(x_axis, head_top_BC)
h_interp = head_fn(x_interp)
peak_locs, peak_props = find_peaks(h_interp, prominence = 0.01)
trough_locs, trough_props = find_peaks(-h_interp, prominence = 0.01)
ax.plot(x_interp, h_interp)
ax.scatter(x_interp[peak_locs], h_interp[peak_locs], fc = 'limegreen', ec = 'black', marker = 'o', zorder = 3)
ax.scatter(x_interp[trough_locs], h_interp[trough_locs], fc = 'magenta', ec = 'black', marker = 's', zorder = 3)
ax.set_ylim(-0.072, 0.1)
twin.plot(bed_profile[:,0], bed_profile[:,1], color = 'darkgray')
twin.set_ylim(16, 19.25)
l = fig.axes[0].legend(artists, ["Head", "Head Peaks", "Head Troughs", "Bed Profile"], loc = 'upper left', bbox_to_anchor = (1.1, 1))
Why doesn't zorder work in this case? I've tried using it but the text still ends up being covered by the bar plot towers.
import numpy as np
from matplotlib import pyplot as plt
Percentage_Differences_1 = np.array([ [7.94*(10**-10),7.94*(10**-9),7.94*(10**-8),7.94*(10**-7),7.94*(10**-6),7.94*(10**-5)],
[7.92*(10**-12),7.92*(10**-11),7.92*(10**-10),7.92*(10**-9),7.92*(10**-8),7.92*(10**-7)],
[7.72*(10**-14),7.72*(10**-13),7.72*(10**-12),7.72*(10**-11),7.72*(10**-10),7.72*(10**-9)],
[5.66*(10**-16),5.66*(10**-15),5.66*(10**-14),5.66*(10**-13),5.66*(10**-12),5.66*(10**-11)],
[1.49*(10**-17),1.49*(10**-16),1.49*(10**-15),1.49*(10**-14),1.49*(10**-13),1.49*(10**-12)],
[2.21*(10**-18),2.21*(10**-17),2.21*(10**-16),2.21*(10**-15),2.21*(10**-14),2.21*(10**-13)] ]) # Layer 1, 12
fig1 = plt.figure(dpi = 120, tight_layout = True)
fig1.set_size_inches(10, 7)
ax1 = fig1.add_subplot(111, projection='3d')
width = depth = 0.3
column_names = ['$10^{-6} m$','$10^{-5} m$','$10^{-4} m$','$10^{-3} m$','$10^{-2} m$','$10^{-1} m$']
row_names = ['$10^{-6} g$','$10^{-5} g$','$10^{-4} g$','$10^{-3} g$','$10^{-2} g$','$10^{-1} g$']
height_names = ['$10^{-2}$','$10^{-4}$','$10^{-6}$','$10^{-8}$','$10^{-10}$','$10^{-12}$','$10^{-14}$','$10^{-16}$','$10^{-18}$']
for x in range(0,6):
for y in range(0,6):
plot1 = ax1.bar3d(x, y, 0, width, depth, np.log10(Percentage_Differences_1[x][y]), color = "#0040bf", alpha=0.3, zorder = 1)
txt1 = ax1.text(x,y,1.15*np.log10(Percentage_Differences_1[x][y]),'{:.2e}'.format(Percentage_Differences_1[y][x]), verticalalignment='top', bbox=dict(facecolor='grey', alpha=0.5), zorder = 2)
ax1.view_init(-140, -30)
ax1.set_xticks(np.linspace(0, 6, num = 6))
ax1.set_yticks(np.linspace(0, 6, num = 6))
ax1.set_xticklabels(column_names)
ax1.set_yticklabels(row_names)
ax1.set_zticklabels(height_names)
ax1.set_xlabel("Mass", labelpad = 13, rotation = 45)
ax1.set_ylabel("Radius", labelpad = 10, rotation = 45)
ax1.set_zlabel("Deviation $\Delta$")
ax1.set_title("1st Initial Condition: $r(0)$ and $r'(0)$ of $\Theta(12) = 2.18 \\times 10^{7} m$", pad = 40)
plt.show()
I've tried using both set_zorder and zorder but the plot still ends up covering the majority of the text labels.
Change your zorder for a number larger than the number of bar objects, 100 for example:
I want to create one figure with two plots like this.
My codes are:
plt.subplot(1,2,1)
plt.hist(biib_neg_return_price, bins = 100, density = True, facecolor = "g")
plt.plot(x_fit, biib_normal_fit, color = "k", linestyle = "solid", linewidth = 1)
plt.xlabel("BIIB negative return price")
plt.ylabel("Frequency")
title_histo = "Histogram of BIIB Negative Return Price"
plt.title(title_histo)
plt.text(-0.4, 25, "skew = %0.2f\n\u03BC = %0.2f\n\u03C3 = %0.2f" % (biib_skew, biib_mu, biib_std))
plt.subplot(1,2,2)
fig, ax = plt.subplots()
ax.plot(alpha_seq, VaR_history_biib_seq, color = "black", label = "Historical data")
ax.plot(alpha_seq, VaR_normal_biib_seq, color = "olive", label = "Fitted Normal Distribution")
ax.legend(loc = 0)
plt.xlabel("Level \u03B1")
plt.ylabel("Value at Risk")
title_VaR = "Value at Risk for BIIB"
plt.title(title_VaR)
However, the results are two figures like this.
Thanks.
You should be able to do it with something like
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.suptitle('Horizontally stacked subplots')
ax1.plot(x, y)
ax2.plot(x, -y)
Like from here.
I'm trying to draw multiple sets of barplot + lineplot from a dataframe using seaborn like the one below (I've already succeeded in drawing one):
Here you can find the dataframe used to produce it => dataframe
What I'd like to achieve is this kind of graph (which I have already succeeded in creating) but repeated for all the possibile product families inside a speicifc product basket ('family' is a drill down level of 'product basket')
Thanks a lot for anyone who will help me. I've tried some looping but probably I'm just doing it wrong.
Here is the code that I've used to draw the above graph:
#select a family
df_perc2=df_perc.query('family=="WORKWEAR & PROTECTIVE CLOTHING"')
#set common axis
fig, ax = plt.subplots()
ax_twin = ax.twinx()
#set boxplot general aspect
fig = plt.gcf()
fig.set_size_inches(30, 10)
sns.set_style("white")
#ship_to_count bars
barplot = sns.barplot(data=df_perc2,
x = 'orders_count',
hue = 'SF_type',
y = 'ship_to_perc',
palette = "Set2",
ax = ax)
#cumulative % line
lineplot = sns.pointplot(data = df_perc2,
x = 'orders_count',
hue = 'SF_type',
y = 'running_perc',
palette = "Set2",
marker ='o',
ax = ax_twin,
legend = False)
#set tick stiles for x and y axis
barplot.set_xticklabels(barplot.get_xmajorticklabels(), fontsize = 18)
barplot.set_yticklabels(barplot.get_yticks().round(2), size = 18)
lineplot.set_yticklabels(lineplot.get_yticks().round(2), size = 18)
#set dynamic title
barplot.set_title('% Ship Tos by # orders for '+''.join(df_perc2['product_basket'].unique())
+
' - '
+
''.join(df_perc2['family'].unique()), fontdict = { 'fontsize': 30}, y = 1.05)
barplot.get_legend().remove()
#set constant line at 90%
plt.axhline(y=0.9, color='g', ls=':', lw=4, label='90th percentile')
lineplot.legend(loc='center right',fontsize='22')
When I use plt.plot(x,y) I get the following in Spyders plot display by default:
However, I want:
black axes lines and white background. How do I set this?
ax4.axes.get_xaxis().set_visible(True)
ax4.spines['bottom'].set_color('black')
ax4.tick_params(axis='x', colors='black')
ax4.tick_params(axis='y', colors='black')
did not work.
Code to get default:
fig = plt.figure(figsize=(8.5,11))
ax4 = fig.add_subplot(3,1,2)
Dist25 = np.load('Dist25.npy')
Dist100 = np.load('Dist100.npy')
r =1
#
ax4.plot(Dist25[0::r,3],Dist25[0::r,0],'or', color = 'xkcd:azure')
ax4.plot(Dist100[0::r,3],Dist100[0::r,0],'<r', color = 'xkcd:chartreuse')
ax4.set_xscale('log')
ax4.set_ylim((1.5,2.5))
ax4.fill_between(Dist25[0::r,3], Dist25[0::r,0] - Dist25[0::r,1], Dist25[0::r,0] + Dist25[0::r,1],
color='xkcd:azure', alpha=0.2)
ax4.fill_between(Dist100[0::r,3], Dist100[0::r,0] - Dist100[0::r,1], Dist100[0::r,0] + Dist100[0::r,1],
color='xkcd:chartreuse', alpha=0.2)
for tick in ax4.xaxis.get_majorticklabels(): # example for xaxis
tick.set_fontsize(18)
for tick in ax4.yaxis.get_majorticklabels(): # example for xaxis
tick.set_fontsize(18)
ax4.set_title('B) Distance from chain', fontsize = 25)
ax4.set_xlabel('Simulation time (ps)', fontsize = 20)
ax4.set_ylabel('Distance (nm)', fontsize = 20)
I solved this by adding:
plt.style.use('classic')
to my code :)