Below is the sample code
import pandas as pd
from causalimpact import CausalImpact
data = pd.read_csv('https://raw.githubusercontent.com/WillianFuks/tfcausalimpact/master/tests/fixtures/arma_data.csv')[['y', 'X']]
data.iloc[70:, 0] += 5
pre_period = [0, 69]
post_period = [70, 99]
ci = CausalImpact(data, pre_period, post_period)
ci.plot()
I wanted to write above generated plot to html or atleast save as image . Is there any solution as type of ci.plot() is nonetype .
https://github.com/WillianFuks/tfcausalimpact
A very dirty (but working) solution would be to:
Get the code of ci.plot() using inspect
import inspect
print(inspect.getsource(ci.plot))
Create a new function based on ci.plot() which actually saves the plot
(or probably it's possible to rewrite the method of the class).
In my case it's function plot2 with a new parameter path.
Its only difference from the original function is the last line.
def plot2(self, path, panels=['original', 'pointwise', 'cumulative'], figsize=(15, 12)):
"""Plots inferences results related to causal impact analysis.
Args
----
panels: list.
Indicates which plot should be considered in the graphics.
figsize: tuple.
Changes the size of the graphics plotted.
Raises
------
RuntimeError: if inferences were not computed yet.
"""
plt = self._get_plotter()
fig = plt.figure(figsize=figsize)
if self.summary_data is None:
raise RuntimeError('Please first run inferences before plotting results')
valid_panels = ['original', 'pointwise', 'cumulative']
for panel in panels:
if panel not in valid_panels:
raise ValueError(
'"{}" is not a valid panel. Valid panels are: {}.'.format(
panel, ', '.join(['"{}"'.format(e) for e in valid_panels])
)
)
# First points can be noisy due approximation techniques used in the likelihood
# optimizaion process. We remove those points from the plots.
llb = self.trained_model.filter_results.loglikelihood_burn
inferences = self.inferences.iloc[llb:]
intervention_idx = inferences.index.get_loc(self.post_period[0])
n_panels = len(panels)
ax = plt.subplot(n_panels, 1, 1)
idx = 1
if 'original' in panels:
ax.plot(pd.concat([self.pre_data.iloc[llb:, 0], self.post_data.iloc[:, 0]]),
'k', label='y')
ax.plot(inferences['preds'], 'b--', label='Predicted')
ax.axvline(inferences.index[intervention_idx - 1], c='k', linestyle='--')
ax.fill_between(
self.pre_data.index[llb:].union(self.post_data.index),
inferences['preds_lower'],
inferences['preds_upper'],
facecolor='blue',
interpolate=True,
alpha=0.25
)
ax.grid(True, linestyle='--')
ax.legend()
if idx != n_panels:
plt.setp(ax.get_xticklabels(), visible=False)
idx += 1
if 'pointwise' in panels:
ax = plt.subplot(n_panels, 1, idx, sharex=ax)
ax.plot(inferences['point_effects'], 'b--', label='Point Effects')
ax.axvline(inferences.index[intervention_idx - 1], c='k', linestyle='--')
ax.fill_between(
inferences['point_effects'].index,
inferences['point_effects_lower'],
inferences['point_effects_upper'],
facecolor='blue',
interpolate=True,
alpha=0.25
)
ax.axhline(y=0, color='k', linestyle='--')
ax.grid(True, linestyle='--')
ax.legend()
if idx != n_panels:
plt.setp(ax.get_xticklabels(), visible=False)
idx += 1
if 'cumulative' in panels:
ax = plt.subplot(n_panels, 1, idx, sharex=ax)
ax.plot(inferences['post_cum_effects'], 'b--',
label='Cumulative Effect')
ax.axvline(inferences.index[intervention_idx - 1], c='k', linestyle='--')
ax.fill_between(
inferences['post_cum_effects'].index,
inferences['post_cum_effects_lower'],
inferences['post_cum_effects_upper'],
facecolor='blue',
interpolate=True,
alpha=0.25
)
ax.grid(True, linestyle='--')
ax.axhline(y=0, color='k', linestyle='--')
ax.legend()
# Alert if points were removed due to loglikelihood burning data
if llb > 0:
text = ('Note: The first {} observations were removed due to approximate '
'diffuse initialization.'.format(llb))
fig.text(0.1, 0.01, text, fontsize='large')
plt.savefig(path)
Call the new function instead:
plot2(ci, 'myplot.png')
Related
I'm using this code to plot my data in boxplot:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon
random_dists = ['Overlap', 'Non overlap', ]
Overlap= [6,6,5,1,3,4,4,3]
non_overlap= [1,2,6,6,1,3,3,3,3,3,5,2,2]
data = [
Overlap,
non_overlap
]
fig, ax1 = plt.subplots(figsize=(6, 6))
fig.canvas.set_window_title('A Boxplot Example')
fig.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25)
# bp = ax1.boxplot(data, notch=0, sym='+', vert=1, whis=1.5)
bp = ax1.boxplot(data)
plt.setp(bp['boxes'], color='black')
plt.setp(bp['whiskers'], color='black')
plt.setp(bp['fliers'], color='red', marker='+')
# Add a horizontal grid to the plot, but make it very light in color
# so we can use it for reading data values but not be distracting
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey',
alpha=0.5)
# Hide these grid behind plot objects
ax1.set_axisbelow(True)
ax1.set_title('overlap and non_overlap against mRS')
# ax1.set_xlabel('Distribution')
# ax1.set_ylabel('Value')
# Now fill the boxes with desired colors
box_colors = ['darkkhaki', 'royalblue']
num_boxes = len(data)
medians = np.empty(num_boxes)
for i in range(num_boxes):
box = bp['boxes'][i]
boxX = []
boxY = []
for j in range(5):
boxX.append(box.get_xdata()[j])
boxY.append(box.get_ydata()[j])
box_coords = np.column_stack([boxX, boxY])
# Alternate between Dark Khaki and Royal Blue
ax1.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2]))
# Now draw the median lines back over what we just filled in
med = bp['medians'][i]
medianX = []
medianY = []
for j in range(2):
medianX.append(med.get_xdata()[j])
medianY.append(med.get_ydata()[j])
ax1.plot(medianX, medianY, 'k')
medians[i] = medianY[0]
# Finally, overplot the sample averages, with horizontal alignment
# in the center of each box
ax1.plot(np.average(med.get_xdata()), np.average(data[i]),
color='w', marker='*', markeredgecolor='k')
# Set the axes ranges and axes labels
ax1.set_xlim(0.5, num_boxes + 0.5)
top = 10 #y-axis
bottom = 0 #y-axis
ax1.set_ylim(bottom, top)
ax1.set_xticklabels(np.repeat(random_dists, 1),
rotation=45, fontsize=8)
pos = np.arange(num_boxes) + 1
# Finally, add a basic legend
fig.text(0.80, 0.08, 'Overlap',
backgroundcolor=box_colors[0], color='black', weight='roman',
size='x-small')
fig.text(0.80, 0.045, 'Non overlap',
backgroundcolor=box_colors[1],
color='white', weight='roman', size='x-small')
fig.text(0.80, 0.015, '*', color='white', backgroundcolor='silver',
weight='roman', size='medium')
fig.text(0.815, 0.013, ' Average Value', color='black', weight='roman',
size='x-small')
plt.show()
What i need is overlap the data into it as a scatter plot just like the picture from this link
I really try hard to use the code on the link and try to search on overstack to find a solution but i'm not that good in coding, also i try using seaborn library but i always get an error that: 'list' object has no attribute 'get' and couldn't fix it
so please any one can help ()
The current version of plt.boxplot() allows plotting most of these elements standard.
Means will be drawn if showmeans is set to True. Its properties can be controlled via the meanprops dictionary. When setting patch_artist=True, instead of just the outline, a filled box will be drawn, boxprops controls how they look.
To draw the scatter plot on top, just call ax1.scatter. The x-positions can be jittered randomly via i + np.random.uniform(-0.4, 0.4). To force them on top of boxplot, their z-order can be changed.
As the fliers are also part of the scatter data, it probably makes sense to leave them out (showfliers=False).
To create a legend, you can collect handles to all desired elements and pass them to ax1.legend(). Note that your boxplots already get labels in the x-axis, so having them also in the legend might be a bit superfluous.
import matplotlib.pyplot as plt
import numpy as np
random_dist_names = ['Overlap', 'Non overlap']
overlap = [6, 6, 5, 1, 3, 4, 4, 3]
non_overlap = [1, 2, 6, 6, 1, 3, 3, 3, 3, 3, 5, 2, 2]
data = [overlap, non_overlap]
fig, ax1 = plt.subplots(figsize=(6, 6))
fig.canvas.set_window_title('A Boxplot Example')
fig.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25)
box_colors = ['darkkhaki', 'royalblue']
scatter_colors = ['purple', 'crimson']
legend_handles = []
for i, (values, box_color, scatter_color) in enumerate(zip(data, box_colors, scatter_colors), start=1):
bp = ax1.boxplot(values, positions=[i], showmeans=True, patch_artist=True, showfliers=False,
boxprops={'edgecolor': 'black', 'facecolor': box_color},
whiskerprops={'color': 'black'}, # flierprops={'color': 'red', 'marker': '+'},
medianprops={'color': 'lime', 'linewidth': 2, 'linestyle': ':'},
meanprops={'markerfacecolor': 'w', 'marker': '*', 'markeredgecolor': 'k', 'markersize': 10})
if i == 1:
legend_handles.append(bp['means'][0])
legend_handles.append(bp['boxes'][0])
ax1.scatter(i + np.random.uniform(-0.4, 0.4, len(values)), values, color=scatter_color, alpha=0.5, zorder=3)
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5)
ax1.set_axisbelow(True)
ax1.set_title('overlap and non_overlap against mRS')
ax1.set_xlim(0.5, len(data) + 0.5)
ax1.set_ylim(ymin=0)
ax1.set_xticklabels(random_dist_names, rotation=0, fontsize=8)
ax1.legend(legend_handles, ['Mean'] + random_dist_names, bbox_to_anchor=[1, -0.1], loc='upper right')
plt.show()
Note that you have very few data points, and they all have integer values, which makes the red dots appear in horizontal lines.
PS: To create something similar with Seaborn, the data has to be organized more similar to a pandas dataframe. Such a dataframe would have one column with all the values, and one column with the category.
The legend can be created more automatically. To also get the means into the legend, a label has to be assigned to the mean via meanprops={..., 'label': 'Mean'}. Unfortunately, this creates one legend entry for every box. These can be skipped by first getting all the legend entries with ax.get_legend_handles_labels() and taking subarrays of the handles and labels.
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
random_dist_names = ['Overlap', 'Non overlap']
overlap = [6, 6, 5, 1, 3, 4, 4, 3]
non_overlap = [1, 2, 6, 6, 1, 3, 3, 3, 3, 3, 5, 2, 2]
data_names = np.repeat(random_dist_names, [len(overlap), len(non_overlap)])
data_values = np.concatenate([overlap, non_overlap])
ax = sns.boxplot(x=data_names, y=data_values, hue=data_names, palette=['darkkhaki', 'royalblue'],
dodge=False, showfliers=False, showmeans=True,
meanprops={'markerfacecolor': 'w', 'marker': '*', 'markeredgecolor': 'k', 'markersize': 10, 'label': 'Mean'})
sns.stripplot(x=data_names, y=data_values, color='red', alpha=0.4)
handles, labels = ax.get_legend_handles_labels()
skip_pos = len(random_dist_names) - 1
ax.legend(handles[skip_pos:], labels[skip_pos:], bbox_to_anchor=(1.02, -0.05), loc='upper right')
plt.tight_layout()
plt.show()
I am using the following script to generate some plots. The problem is sometimes the scientific notation is overlapping with the title.
Is there a way to fix this like moving the plot a little bit down?
# init
u = {}
o = {}
# create figure
fig = plt.figure()
# x-Axis (timesteps)
i = np.array(i)
for key in urbs_values.keys():
# y-Axis (values)
u[key] = np.array(urbs_values[key])
o[key] = np.array(oemof_values[key])
# draw plots
plt.plot(i, u[key], label='urbs_'+str(key), linestyle='None', marker='x')
plt.ticklabel_format(axis='y', style='sci', scilimits=(0, 0))
plt.plot(i, o[key], label='oemof_'+str(key), linestyle='None', marker='.')
plt.ticklabel_format(axis='y', style='sci', scilimits=(0, 0))
# plot specs
plt.xlabel('Timesteps [h]')
plt.ylabel('Flow [MWh]')
plt.title(site+' '+name)
plt.grid(True)
plt.tight_layout(rect=[0,0,0.7,1])
plt.legend(bbox_to_anchor=(1.025, 1), loc=2, borderaxespad=0)
# plt.show()
Example:
You can change the position of the title by providing a value for the y parameter in plt.title(...), e.g., plt.title(site+' '+name, y=1.1).
You can edit the tittle position this way:
# plot specs
plt.xlabel('Timesteps [h]')
plt.ylabel('Flow [MWh]')
plt.title(site+' '+name)
ttl = plt.title
ttl.set_position([.5, 1.02])
plt.grid(True)
plt.tight_layout(rect=[0,0,0.7,1])
plt.legend(bbox_to_anchor=(1.025, 1), loc=2, borderaxespad=0)
# plt.show()
tuning the '1.02' should do the trick
I want to make a figure which consist of a frame with 4 figures, but in each figure there are three subplots. I am using the current version of Matplotlib
I show my code in order to do each individual figure, the point as I comment before, is how put 4 of this plots together in order to make a single figure
filename1 = "file1.txt"
filename2 = "file2.txt"
filename3 = "file3.txt"
datalist1 = np.loadtxt(filename1)
datalist2 = np.loadtxt(filename2)
datalist3 = np.loadtxt(filename3)
f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=True)
#First subplot
ax1.plot(datalist1[:,0], datalist1[:,1], 'k-')
ax1.plot(datalist2[:,0], datalist2[:,1], 'b-')
ax1.plot(datalist2[:,0], datalist2[:,2], 'g-')
ax1.plot(datalist2[:,0], datalist2[:,3], 'r-')
ax1.plot(datalist3[:,0], datalist3[:,1], 'k--')
ax1.set_ylim(-1.2, 1.2)
ax1.set_xlim(0, 10)
major_ticks_x = np.arange(0.0, 11, 2.0)
minor_ticks_x = np.arange(0.0, 11, 1.0)
major_ticks_y = np.arange(-1, 1.05, 1.0)
minor_ticks_y = np.arange(-1, 1.05, 0.25)
ax1.set_yticks(major_ticks_y)
ax1.set_yticks(minor_ticks_y, minor=True)
#Second subplot
ax2.plot(datalist1[:,0], datalist1[:,2], 'k-')
ax2.plot(datalist2[:,0], datalist2[:,4], 'b-')
ax2.plot(datalist2[:,0], datalist2[:,5], 'g-')
ax2.plot(datalist2[:,0], datalist2[:,6], 'r-')
ax2.plot(datalist3[:,0], datalist3[:,1], 'k--')
ax2.set_ylim(-1.2, 1.2)
ax2.set_xlim(0, 10)
ax2.set_yticks(major_ticks_y)
ax2.set_yticks(minor_ticks_y, minor=True)
#Third subplot
ax3.plot(datalist1[:,0], datalist1[:,3], 'k-')
ax3.plot(datalist2[:,0], datalist2[:,7], 'b-')
ax3.plot(datalist2[:,0], datalist2[:,8], 'g-')
ax3.plot(datalist2[:,0], datalist2[:,9], 'r-')
ax3.plot(datalist3[:,0], datalist3[:,1], 'k--')
ax3.set_ylim(-1.2, 1.2)
ax3.set_xlim(0, 10)
ax3.set_yticks(major_ticks_y)
ax3.set_yticks(minor_ticks_y, minor=True)
ax3.set_xticks(major_ticks_x)
ax3.set_xticks(minor_ticks_x, minor=True)
ax3.set_xlabel(r"$t$")
f.subplots_adjust(hspace=0.0)
plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
The plot that I want to obtain is somtehing like this, in a single figure:
Somebody knows how can be do it?? Thanks for your attention.
OK, I'll bite. It is unclear what you want, but I assume you want 12 subplots (6 rows, 2 columns) grouped into 4 groups with shared x-axis.
As usual creating the subplots and plotting is easy. Sharing x-axis is straightforward as well, but requires some manual work. You can either set up the shared x-axis during the subplot creation or modify it after. I think modifying after is simpler.
Sorry for the manual part in the middle - it is possible to automate obviously.
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
fig, axx = plt.subplots(6, 2, figsize=(10,14))
## merge axis
axx[0, 0].get_shared_x_axes().join(axx[0, 0], axx[2, 0])
axx[0, 0].set_xticklabels([])
axx[1, 0].get_shared_x_axes().join(axx[1, 0], axx[2, 0])
axx[1, 0].set_xticklabels([])
axx[0, 1].get_shared_x_axes().join(axx[0, 1], axx[2, 1])
axx[0, 1].set_xticklabels([])
axx[1, 1].get_shared_x_axes().join(axx[1, 1], axx[2, 1])
axx[1, 1].set_xticklabels([])
axx[3, 0].get_shared_x_axes().join(axx[3, 0], axx[5, 0])
axx[3, 0].set_xticklabels([])
axx[4, 0].get_shared_x_axes().join(axx[4, 0], axx[5, 0])
axx[4, 0].set_xticklabels([])
axx[3, 1].get_shared_x_axes().join(axx[3, 1], axx[5, 1])
axx[3, 1].set_xticklabels([])
axx[4, 1].get_shared_x_axes().join(axx[4, 1], axx[5, 1])
axx[4, 1].set_xticklabels([])
# plot some data
for i, row in enumerate(axx):
for j, cell in enumerate(row):
if i <= 2:
cell.plot(np.random.rand(100))
else:
cell.plot(np.random.rand(200))
Here is the result.
I'm using subplot2grid and trying make fill_between() work for the second subplot.
It does work, but for some reason it shows orange dots. How can I get rid of those dots?
Notice the orange dots in the second subplot
In the last 3 lines of code is where the fill_between() appears, but posting all the relevant code for the chart (the data is in pandas dataframes)
length = len(df.index)
fig6 = plt.figure(figsize=(14,11))
ax1_f6 = plt.subplot2grid((9,1),(0,0), rowspan=5, colspan=1)
titulo = "{0} ".format(assets[0])
fig6.suptitle(titulo, fontsize=15, color='#0079a3')
# V.1) data for first subplot
x6 = mdates.date2num(df.index[-length:].to_pydatetime())
y6 = df.PX_LAST[-length:].values
z6 = df.trend_noise_thr_mean[-length:].values
cmap = ListedColormap(['r','y','g'])
norm = BoundaryNorm([-1.5,-1,0,1,1.5], cmap.N)
points = np.array([x6,y6]).T.reshape(-1, 1, 2)
segments= np.concatenate([points[:-1], points[1:]], axis=1)
lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(z6)
lc.set_linewidth(3)
ax1_f6=plt.gca()
ax1_f6.add_collection(lc)
ax1_f6.set_xlim(x6.min(), x6.max())
ax1_f6.set_ylim(y6.min(), y6.max())
ax1_f6.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y'))
ax1_f6.plot(df.emaw.index[-length:], df.emaw[-length:], '-', lw=0.7, label='EMA', color='r')
# V.2) data of the second subplot
ax2_f6 = plt.subplot2grid((9,1),(6,0), rowspan=4, colspan=1, sharex=ax1_f6)
axb2_f6 = ax2_f6.twinx()
test = (df.noise - df.mean)
axb2_f6.plot_date(test.index[-length:], test[-length:], lw=1, label='test')
axb2_f6.fill_between(test.index, test, 0, where=(test >= 0), facecolor='g', alpha=0.3, interpolate=True)
axb2_f6.fill_between(test.index, test, 0, where=(test < 0), facecolor='r', alpha=0.3, interpolate=True)
plot_date uses marker='o' by default. Pass marker=None to the method to get rid of the dots:
axb2_f6.plot_date(test.index[-length:], marker=None, test[-length:], lw=1, label='test')
I'm wondering how do I force my subplots to share the y-axis range.
This is my code:
f, axes = plt.subplots(7, 1, sharex='col', sharey='row', figsize=(15, 30))
distance = []
for i in range(simulations):
delta = numpy.zeros((simulations+samples, simulations+samples))
data_x = sample_x[i*samples:(i*samples)+samples] + ensamble_x
data_y = sample_y[i*samples:(i*samples)+samples] + ensamble_y
for j in range(simulations+samples):
for k in range(simulations+samples):
if j <= k:
dist = similarity_measure((data_x[j].flatten(), data_y[j].flatten()), (data_x[k].flatten(), data_y[k].flatten()))
delta[j, k] = delta[k, j] = dist
delta = 1-((delta+1)/2)
delta /= numpy.max(delta)
model = manifold.TSNE(n_components=2, random_state=0, metric='precomputed')
coords = model.fit_transform(delta)
mds = manifold.MDS(n_components=2, max_iter=3000, eps=1e-9, random_state=0,
dissimilarity="precomputed", n_jobs=1)
coords = mds.fit(delta).embedding_
close, far = find_distance(coords[:samples, :], coords[samples+i, :])
distance.append((close, far))
axes[i].scatter(coords[:samples, 0], coords[:samples, 1], marker='x', c=colors[i], s=50, edgecolor='None')
axes[i].scatter(coords[samples:, 0], coords[samples:, 1], marker='o', c=colors, s=50, edgecolor='None')
axes[i].scatter(coords[close, 0], coords[close, 1], marker='s', facecolor="none", c=colors[i], s=50, edgecolor='None')
axes[i].scatter(coords[far, 0] , coords[far, 1] , marker='s', facecolor="none", c=colors[i], s=50, edgecolor='None')
axes[i].set_title('Simulation '+str(i+1), fontsize=20)
markers = []
labels = [str(n+1) for n in range(simulations)]
for i in range(simulations):
markers.append(Line2D([0], [0], linestyle='None', marker="o", markersize=10, markeredgecolor="none", markerfacecolor=colors[i]))
lgd = plt.legend(markers, labels, numpoints=1, bbox_to_anchor=(1.0, -0.055), ncol=simulations)
plt.tight_layout()
plt.ylim(-1, 1)
plt.axis('equal')
plt.savefig('Simulations.pdf', bbox_extra_artists=(lgd,), format='pdf', bbox_inches='tight')
And it's result:
As can be seen, the y axis limits differs from one subplot to another.
I'd like to use the max/min range generated.
Thank you.
EDTI: MINIMAL EXAMPLE
%matplotlib inline
from sklearn.preprocessing import normalize
from sklearn import manifold
from matplotlib import pyplot as plt
from matplotlib.lines import Line2D
import numpy
import itertools
f, axes = plt.subplots(7, 1, sharex='col', sharey='row', figsize=(15, 30))
distance = []
for i in range(7):
delta = numpy.random.randint(0, 100, (100, 100))
axes[i].scatter(delta[:, 0], delta[:, 1], marker='x', c='r', s=50, edgecolor='None')
axes[i].set_title('Simulation '+str(i+1), fontsize=20)
axes[i].set_ylim(0, 100)
markers = []
plt.tight_layout()
plt.axis('equal')
Your 1st line
f, axes = plt.subplots(7, 1, sharex='col', sharey='row', figsize=(15, 30))
has an inappropriate value for the sharey parameter. Using sharey='row' you're asking that all the subplots in each row share the same y axis, but each of your subplots is in a row by itself, so you see no sharing.
If you try sharey=True or sharey='col' you'll get what you want.
Addendum
The following code
In [34]: a = np.random.random(21)
In [35]: b = a+5
In [36]: x = np.arange(21)
In [37]: f, (ax, bx) = plt.subplots(2,1,sharey='row') # like yours
In [38]: ax.plot(x,a)
Out[38]: [<matplotlib.lines.Line2D at 0x7f5b98004f98>]
In [39]: bx.plot(x,b)
Out[39]: [<matplotlib.lines.Line2D at 0x7f5b980238d0>]
In [40]: f, (ax, bx) = plt.subplots(2,1,sharey='col') # like mine
In [41]: ax.plot(x,a)
Out[41]: [<matplotlib.lines.Line2D at 0x7f5b94764dd8>]
In [42]: bx.plot(x,b)
Out[42]: [<matplotlib.lines.Line2D at 0x7f5b98038198>]
In [43]:
gives me the following two plots. Can you spot a single difference?
You have to add a line axes[i].set_ylim(ymin,ymax) within the main loop where you make the plot. For example, below the following line
axes[i].set_title('Simulation '+str(i+1), fontsize=20)
add:
axes[i].set_ylim(-1,1)
That should solve it.
In your example, you are calling plt.ylim instead, but from the documentation "Get or set the y-limits of the current axes", which in your case correspond to the last axes.
Answer to the minimalist example:
As you see from your plot, all the axis but the last, have the same limits in the y-coordinate. Everytime you call plt.*, you affect the behaviour of the last axis. Your last call to plt.axis('equal') is what affects the last plot. Just remove this line.