Wondering if its possible to create subplots of a subplot. The reason I am looking to do this is to create 3 broken axis charts on a single plot. I understand how to create a single broken axis chart with the example code below, but since a broken axis chart requires the use of subplots I am now in a position where I am trying to use subplots to create 3 columns, then subplot those columns into a subplot with 2 rows to create the broken axis chart. See below for visual explanation.
"""
EXAMPLE OF A SINGLE BROKEN AXIS CHART
"""
import matplotlib.pyplot as plt
import numpy as np
# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
ptsA = np.array([
0.015, 0.166, 0.133, 0.159, 0.041, 0.024, 0.195, 0.039, 0.161, 0.018,
0.143, 0.056, 0.125, 0.096, 0.094, 0.051, 0.043, 0.021, 0.138, 0.075,
0.109, 0.195, 0.050, 0.074, 0.079, 0.155, 0.020, 0.010, 0.061, 0.008])
# Now let's make two outlier points which are far away from everything.
ptsA[[3, 14]] += .8
# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
ptsB = np.array([
0.015, 0.166, 0.133, 0.159, 0.041, 0.024, 0.195, 0.039, 0.161, 0.018,
0.143, 0.056, 0.125, 0.096, 0.094, 0.051, 0.043, 0.021, 0.138, 0.075,
0.109, 0.195, 0.050, 0.074, 0.079, 0.155, 0.020, 0.010, 0.061, 0.008])
# Now let's make two outlier points which are far away from everything.
ptsB[[1, 7, 9, 13, 15]] += .95
# If we were to simply plot pts, we'd lose most of the interesting
# details due to the outliers. So let's 'break' or 'cut-out' the y-axis
# into two portions - use the top (ax) for the outliers, and the bottom
# (ax2) for the details of the majority of our data
f, (ax, ax2) = plt.subplots(2, 1, sharex=True)
# plot the same data on both axes
ax.plot(ptsB)
ax2.plot(pts)
# zoom-in / limit the view to different portions of the data
ax.set_ylim(.78, 1.) # outliers only
ax2.set_ylim(0, .22) # most of the data
# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.xaxis.tick_bottom()
# This looks pretty good, and was fairly painless, but you can get that
# cut-out diagonal lines look with just a bit more work. The important
# thing to know here is that in axes coordinates, which are always
# between 0-1, spine endpoints are at these locations (0,0), (0,1),
# (1,0), and (1,1). Thus, we just need to put the diagonals in the
# appropriate corners of each of our axes, and so long as we use the
# right transform and disable clipping.
d = .015 # how big to make the diagonal lines in axes coordinates
# arguments to pass plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d, +d), (-d, +d), **kwargs) # top-left diagonal
ax.plot((1 - d, 1 + d), (-d, +d), **kwargs) # top-right diagonal
kwargs.update(transform=ax2.transAxes) # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs) # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) # bottom-right diagonal
# What's cool about this is that now if we vary the distance between
# ax and ax2 via f.subplots_adjust(hspace=...) or plt.subplot_tool(),
# the diagonal lines will move accordingly, and stay right at the tips
# of the spines they are 'breaking'
plt.show()
Desired Output
3 subplots, each containing 2 subplots
First of all you cannot create a subplot of a subplot. Subplots are axes objects placed in a figure and an axes cannot have "child axes".
The solution to your problem would be to create 6 subplots and apply sharex=True to the respective axes.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(17, 6)
data[15:, 3:] = np.random.rand(2, 3)+3.
markers=["o", "p", "s"]
colors=["r", "g", "b"]
fig=plt.figure(figsize=(10, 4))
axes = []
for i in range(3):
ax = fig.add_subplot(2,3,i+1)
axes.append(ax)
for i in range(3):
ax = fig.add_subplot(2,3,i+4, sharex=axes[i])
axes.append(ax)
for i in range(3):
# plot same data in both top and down axes
axes[i].plot(data[:,i], data[:,i+3], marker=markers[i], linestyle="", color=colors[i])
axes[i+3].plot(data[:,i], data[:,i+3], marker=markers[i], linestyle="", color=colors[i])
for i in range(3):
axes[i].spines['bottom'].set_visible(False)
axes[i+3].spines['top'].set_visible(False)
axes[i].xaxis.tick_top()
axes[i].tick_params(labeltop='off') # don't put tick labels at the top
axes[i+3].xaxis.tick_bottom()
axes[i].set_ylim([3,4])
axes[i+3].set_ylim([0,1])
axes[i].set_xlim([0,1])
#adjust space between subplots
plt.subplots_adjust(hspace=0.08, wspace=0.4)
plt.show()
Related
I am trying to rotate the radial tick labels on the attached plot.
Why does matplotlib not rotate them when I have the 'rotation' command specified?
I would then like to shift the labels in the radial direction. Is there an equivalent of the 'pad' command with the polar charts?
import numpy as np
import matplotlib.pyplot as plt
import math
Graph_title = "Radar Plot"
def radarplot():
ax = plt.subplot(111, polar=True)
# INPUT DATA
n_directions = 12
angles = [n / float(n_directions) * 2 * math.pi for n in range(n_directions)]
data = [3.0, 3.0, 3.0, 3.0, 2.0, 2.5, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0]
# Add the last element of the list to the list. This is necessary or the line from 330 deg to 0 degree does not join up on the plot.
angles = np.append(angles, angles[:1])
data = np.append(data, data[:1])
ax.plot(angles, data, linewidth=2, linestyle='solid', color = 'red')
# Radial tick parameters
radial_ticks = [0.00, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00]
ax.set_rlabel_position(45)
ax.set_rorigin(0)
plt.yticks(radial_ticks, color='black', size=8)
ax.set_yticklabels(radial_ticks, rotation = 45, zorder = 500)
# X Tick parameters
plt.xticks(angles, color='black', size=10, zorder = 5)
ax.tick_params(axis='x', which='major', pad=3)
ax.set_theta_zero_location("N") # Sets the labels initial position to 0 degrees
ax.set_theta_direction("clockwise") # Set the labels to rotate clockwise
plt.savefig(Graph_title +".png", figsize = [6.4, 5], dpi=1000)
plt.show()
plt.close()
radarplot()
Recently I wanted to achieve the same thing as you and here is the solution that I came up with.
Suppress the automatic r tick labels using the command ax.set_yticklabels([])
For each radial tick define a tick list, a position list, and an alignment list.
Using the text command write the values in the tick list at the radial locations specified by the position list with alignment specified by the alignment list.
Essentially the r ticks can be moved along the radial direction by changing the values in the position list.
Make sure that the text command is specified with transform=ax.transData option.
import numpy as np
import matplotlib.pyplot as plt
import math
Graph_title = "Radar Plot"
def radarplot():
ax = plt.subplot(111, polar=True)
# INPUT DATA
n_directions = 12
angles = [n / float(n_directions) * 2 * math.pi for n in range(n_directions)]
data = [3.0, 3.0, 3.0, 3.0, 2.0, 2.5, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0]
# Add the last element of the list to the list. This is necessary or the line from 330 deg to 0 degree does not join up on the plot.
angles = np.append(angles, angles[:1])
data = np.append(data, data[:1])
ax.plot(angles, data, linewidth=2, linestyle='solid', color = 'red')
r_ticks = [0.00, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00] #tick list
r_ticks_pos = [0.20, 0.65, 1.15, 1.65, 2.15, 2.65, 3.25] #radial position list (CHANGE THESE VALUES TO MOVE EACH TICK RADIALLY INDIVIDUALLY)
r_ticks_h_align = ['center','center','center','center','center','center','center'] #horizontal alignment list
r_ticks_v_align = ['center','center','center','center','center','center','center'] #vertical alignment list
r_label_angle = 45 #theta angle
# Radial tick parameters
ax.set_rlabel_position(r_label_angle)
ax.set_rorigin(0)
ax.set_yticklabels([])
ax.set_rticks(r_ticks)
ax.set_rlabel_position(r_label_angle)
#write the ticks using the text command
for rtick, rtick_pos, rtick_ha, rtick_va in zip(r_ticks, r_ticks_pos, r_ticks_h_align, r_ticks_v_align):
plt.text(np.radians(r_label_angle), rtick_pos, r'$'+str(rtick)+'$', ha=rtick_ha, va=rtick_va, transform=ax.transData, rotation=-45, fontsize=8)
# X Tick parameters
plt.xticks(angles, color='black', size=10, zorder = 5)
ax.tick_params(axis='x', which='major', pad=3)
ax.set_theta_zero_location("N") # Sets the labels initial position to 0 degrees
ax.set_theta_direction("clockwise") # Set the labels to rotate clockwise
plt.savefig(Graph_title +".png", figsize = [6.4, 5], dpi=1000)
plt.show()
plt.close()
radarplot()
And the result:
I meet the same problem, and I only solved the rotation problem. axis='x' failed to control the rotation, only axis='both' can work.
ax.tick_params(
axis='both',
labelrotation=-45.,
)
I am trying to solve the pad problem.
I've seen plenty of examples online of x-axis alignment for matplotlib Table with charts, but I can't figure out how to y-axis align my table. The following code produces the table pictured after it.
# For minimum viable example
dfx = [['ARS FX', 0.025346713729, 0.028238, 0.021889, 0.07701426, 0.0, 35, 39, '14.7%', 0.0, 0.07701426], ['BRL FX',1.83316130513e-05,0.025746,-0.072473, 0.143642325, 0.0, 40, 45, '12.3%', 0.0, 0.143642325], ['EUR FX', -0.301254060209, -0.300762, -0.290554, 0.0, -0.30127866, -60, -40, '5.2%', -0.30127866, 0.0], ['ZAR FX', 0.0515621470331, 0.053191, 0.044245, 0.07344438, 0.0, 10, 29, '14.1%', 0.0, 0.07344438], ['AR Eqity', 3.68762762118e-06, 0.0,0.0, 0.08817912, 0.0, 45, 45, '23.9%', 0.0, 0.08817912]]
dfx = pd.DataFrame(dfx)
dfx.columns = ['IdeaName', 'ModelWeight', 'Exposure_FXA', 'Exposure','Adj_Ubound', 'Adj_Lbound', 'lt_rob', 'st_rob', 'implied_vol', 'Lower Bound', 'Upper Bound']
# Plot
_, ax = plt.subplots()
dfx[['Lower Bound']].plot(kind='barh',ax=ax,color='red')
dfx[['Upper Bound']].plot(kind='barh',ax=ax,color='green')
plt.plot(dfx['ModelWeight'],range(len(dfx)), linestyle="", markersize=5, marker="o", color="#ff6600", label="ModelWeight", markeredgecolor="k")
plt.plot(dfx['Exposure'],range(len(dfx)), linestyle="", markersize=5, marker="o", color='lightblue', label="Exposure", markeredgecolor="k")
# Add a table at the bottom of the axes
columns = ['LT','ST','Vol']
the_table = ax.table(cellText=dfx[['lt_rob','st_rob','implied_vol']].values,
rowLabels=list(dfx['IdeaName']),
# rowColours=colors,
colWidths=[0.1 for x in columns],
colLabels=columns,
cellLoc='center',
loc=15)
the_table.auto_set_font_size(False)
the_table.set_fontsize(9)
the_table.scale(1, 1.05)
plt.subplots_adjust(left=0.4)
plt.yticks([])
plt.legend()
plt.show()
As you can see, despite me manually playing with the_table.scale() to get it as close as possible, I can't get the rows aligned with my bars, since the column headers of the table are taking up the first row.
Any help appreciated. Thanks.
The following would put the table into a bounding box that is one nth larger than the number of bars n. One then needs to make sure the margins within the axes are correct as well as the subplot parameter. The below only adjusts the vertical direction (the horizontal direction needs to be done by hand for longer labels).
import numpy as np
import matplotlib.pyplot as plt
data = np.random.randint(1,999,size=(10,4))
col = list("ABCD")
row = np.arange(1, len(data)+1)
n = len(data) # number of bars
barwidth = 0.8 # bar width
t = 0.05
b = 0.125
# Plot
fig, ax = plt.subplots()
fig.subplots_adjust(left=0.4, top=1-t-(1-t-b)/(n+1))
ax.margins(y=(1-barwidth)/2/n)
ax.barh(row, data[:,0], height=barwidth, label="bars", )
the_table = ax.table(cellText=data,
rowLabels=row,
colLabels=col,
cellLoc='center',
bbox=(-0.6, 0.0, 0.6, (n+1) / n))
the_table.auto_set_font_size(False)
the_table.set_fontsize(9)
fig.canvas.draw() # need to draw the figure twice
plt.yticks([])
plt.legend()
plt.show()
Wondering if its possible to create subplots of a subplot. The reason I am looking to do this is to create 3 broken axis charts on a single plot. I understand how to create a single broken axis chart with the example code below, but since a broken axis chart requires the use of subplots I am now in a position where I am trying to use subplots to create 3 columns, then subplot those columns into a subplot with 2 rows to create the broken axis chart. See below for visual explanation.
"""
EXAMPLE OF A SINGLE BROKEN AXIS CHART
"""
import matplotlib.pyplot as plt
import numpy as np
# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
ptsA = np.array([
0.015, 0.166, 0.133, 0.159, 0.041, 0.024, 0.195, 0.039, 0.161, 0.018,
0.143, 0.056, 0.125, 0.096, 0.094, 0.051, 0.043, 0.021, 0.138, 0.075,
0.109, 0.195, 0.050, 0.074, 0.079, 0.155, 0.020, 0.010, 0.061, 0.008])
# Now let's make two outlier points which are far away from everything.
ptsA[[3, 14]] += .8
# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
ptsB = np.array([
0.015, 0.166, 0.133, 0.159, 0.041, 0.024, 0.195, 0.039, 0.161, 0.018,
0.143, 0.056, 0.125, 0.096, 0.094, 0.051, 0.043, 0.021, 0.138, 0.075,
0.109, 0.195, 0.050, 0.074, 0.079, 0.155, 0.020, 0.010, 0.061, 0.008])
# Now let's make two outlier points which are far away from everything.
ptsB[[1, 7, 9, 13, 15]] += .95
# If we were to simply plot pts, we'd lose most of the interesting
# details due to the outliers. So let's 'break' or 'cut-out' the y-axis
# into two portions - use the top (ax) for the outliers, and the bottom
# (ax2) for the details of the majority of our data
f, (ax, ax2) = plt.subplots(2, 1, sharex=True)
# plot the same data on both axes
ax.plot(ptsB)
ax2.plot(pts)
# zoom-in / limit the view to different portions of the data
ax.set_ylim(.78, 1.) # outliers only
ax2.set_ylim(0, .22) # most of the data
# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.xaxis.tick_bottom()
# This looks pretty good, and was fairly painless, but you can get that
# cut-out diagonal lines look with just a bit more work. The important
# thing to know here is that in axes coordinates, which are always
# between 0-1, spine endpoints are at these locations (0,0), (0,1),
# (1,0), and (1,1). Thus, we just need to put the diagonals in the
# appropriate corners of each of our axes, and so long as we use the
# right transform and disable clipping.
d = .015 # how big to make the diagonal lines in axes coordinates
# arguments to pass plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d, +d), (-d, +d), **kwargs) # top-left diagonal
ax.plot((1 - d, 1 + d), (-d, +d), **kwargs) # top-right diagonal
kwargs.update(transform=ax2.transAxes) # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs) # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) # bottom-right diagonal
# What's cool about this is that now if we vary the distance between
# ax and ax2 via f.subplots_adjust(hspace=...) or plt.subplot_tool(),
# the diagonal lines will move accordingly, and stay right at the tips
# of the spines they are 'breaking'
plt.show()
Desired Output
3 subplots, each containing 2 subplots
First of all you cannot create a subplot of a subplot. Subplots are axes objects placed in a figure and an axes cannot have "child axes".
The solution to your problem would be to create 6 subplots and apply sharex=True to the respective axes.
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(17, 6)
data[15:, 3:] = np.random.rand(2, 3)+3.
markers=["o", "p", "s"]
colors=["r", "g", "b"]
fig=plt.figure(figsize=(10, 4))
axes = []
for i in range(3):
ax = fig.add_subplot(2,3,i+1)
axes.append(ax)
for i in range(3):
ax = fig.add_subplot(2,3,i+4, sharex=axes[i])
axes.append(ax)
for i in range(3):
# plot same data in both top and down axes
axes[i].plot(data[:,i], data[:,i+3], marker=markers[i], linestyle="", color=colors[i])
axes[i+3].plot(data[:,i], data[:,i+3], marker=markers[i], linestyle="", color=colors[i])
for i in range(3):
axes[i].spines['bottom'].set_visible(False)
axes[i+3].spines['top'].set_visible(False)
axes[i].xaxis.tick_top()
axes[i].tick_params(labeltop='off') # don't put tick labels at the top
axes[i+3].xaxis.tick_bottom()
axes[i].set_ylim([3,4])
axes[i+3].set_ylim([0,1])
axes[i].set_xlim([0,1])
#adjust space between subplots
plt.subplots_adjust(hspace=0.08, wspace=0.4)
plt.show()
I am trying to make four sets of plots in a 2x2 or 1x4 grid. Each set then has three more panels, say, a scatter plot with histograms of the x- and y-axes on the sides.
Instead of setting the axes for all 12 plots, I'd like to divide my canvas into 4 parts, and then divide each one individually. For example,
def plot_subset():
# these coords are normalized to this subset of plots
pos_axScatter=[0.10, 0.10, 0.65, 0.65]
pos_axHistx = [0.10, 0.75, 0.65, 0.20]
pos_axHisty = [0.75, 0.10, 0.20, 0.20]
axScatter = plt.axes(pos_axScatter)
axHistx = plt.axes(pos_axHistx)
axHisty = plt.axes(pos_axHisty)
def main():
# need to divide the canvas to a 2x2 grid
plot_subset(1)
plot_subset(2)
plot_subset(3)
plot_subset(4)
plt.show()
I have tried GridSpec and subplots but cannot find a way to make plot_subset() work in the normalized space. Any help would be much appreciated!
You can use BboxTransformTo() to do this:
from matplotlib import transforms
fig = plt.figure(figsize=(16, 4))
fig.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.04, 0.04)
gs1 = plt.GridSpec(1, 4)
gs2 = plt.GridSpec(4, 4)
for i in range(4):
bbox = gs1[0, i].get_position(fig)
t = transforms.BboxTransformTo(bbox)
fig.add_axes(t.transform_bbox(gs2[:3, :3].get_position(fig)))
fig.add_axes(t.transform_bbox(gs2[3, :3].get_position(fig)))
fig.add_axes(t.transform_bbox(gs2[:3, 3].get_position(fig)))
the output:
This question already has an answer here:
How to plot f(x) as x goes to infinity with matplotlib?
(1 answer)
Closed 8 years ago.
Please look at my code and help me.
I'm writing a code the approximates the Derivative of a function. To visually check how close my approximation is with the real derivative, I'm plotting both of them together.
My problem is when the function is not defined at zero, like 1/x with a derivative of '1/x^2.
Thanks in advance.
# -*- coding: utf-8 -*-
from pylab import *
import math
def Derivative(f,x, Tol = 10e-5, Max = 20):
try:
k = 2
D_old = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))
k = 3
D_new = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))
E_old = abs(D_new - D_old)
while True:
D_old = D_new
k+=1
D_new = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))
E_new = abs(D_old - D_new)
if E_new < Tol or E_new >= E_old or k >= Max:
return D_old
except:
return nan
def Fa(x):
return math.sin(2*math.pi*x)
def Fap(x):
return 2*math.pi*math.cos(2*math.pi*x)
def Fb(x):
return x**2
def Fbp(x):
return 2*x
def Fc(x):
return 1.0/x
def Fcp(x):
if abs(x)<0.01:
return 0
else:
return -1.0/x**2
def Fd(x):
return abs(x)
def Fdp(x):
return 1 #since it's x/sqrt(x**2)
# Plot of Derivative Fa
xx = arange(-1, 1, 0.01) # A Numpy vector of x-values
yy = [Derivative(Fa, x) for x in xx] # Vector of f’ approximations
plot(xx, yy, 'r--', linewidth = 5) # solid red line of width 5
yy2 = [Fap(x) for x in xx]
plot(xx, yy2, 'b--', linewidth = 2) # solid blue line of width 2
# Plot of Derivative Fb
yy = [Derivative(Fb, x) for x in xx] # Vector of f’ approximations
plot(xx, yy, 'g^', linewidth = 5) # solid green line of width 5
yy2 = [Fbp(x) for x in xx]
plot(xx, yy2, 'y^', linewidth = 2) # solid yellow line of width 2
"1/x" is an infinite function and you can not plot a function that is not defined to zero.
You can only plot the function with a broken axis.
For the broken axis, you can follow the suggestion of wwii in comments or you can follow this tutorial for matplotlib.
This tutorial show how you can just use two subplots to create the effect you desire.
Here the example code:
"""
Broken axis example, where the y-axis will have a portion cut out.
"""
import matplotlib.pylab as plt
import numpy as np
# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
pts = np.array([ 0.015, 0.166, 0.133, 0.159, 0.041, 0.024, 0.195,
0.039, 0.161, 0.018, 0.143, 0.056, 0.125, 0.096, 0.094, 0.051,
0.043, 0.021, 0.138, 0.075, 0.109, 0.195, 0.05 , 0.074, 0.079,
0.155, 0.02 , 0.01 , 0.061, 0.008])
# Now let's make two outlier points which are far away from everything.
pts[[3,14]] += .8
# If we were to simply plot pts, we'd lose most of the interesting
# details due to the outliers. So let's 'break' or 'cut-out' the y-axis
# into two portions - use the top (ax) for the outliers, and the bottom
# (ax2) for the details of the majority of our data
f,(ax,ax2) = plt.subplots(2,1,sharex=True)
# plot the same data on both axes
ax.plot(pts)
ax2.plot(pts)
# zoom-in / limit the view to different portions of the data
ax.set_ylim(.78,1.) # outliers only
ax2.set_ylim(0,.22) # most of the data
# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.xaxis.tick_bottom()
# This looks pretty good, and was fairly painless, but you can get that
# cut-out diagonal lines look with just a bit more work. The important
# thing to know here is that in axes coordinates, which are always
# between 0-1, spine endpoints are at these locations (0,0), (0,1),
# (1,0), and (1,1). Thus, we just need to put the diagonals in the
# appropriate corners of each of our axes, and so long as we use the
# right transform and disable clipping.
d = .015 # how big to make the diagonal lines in axes coordinates
# arguments to pass plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d,+d),(-d,+d), **kwargs) # top-left diagonal
ax.plot((1-d,1+d),(-d,+d), **kwargs) # top-right diagonal
kwargs.update(transform=ax2.transAxes) # switch to the bottom axes
ax2.plot((-d,+d),(1-d,1+d), **kwargs) # bottom-left diagonal
ax2.plot((1-d,1+d),(1-d,1+d), **kwargs) # bottom-right diagonal
# What's cool about this is that now if we vary the distance between
# ax and ax2 via f.subplots_adjust(hspace=...) or plt.subplot_tool(),
# the diagonal lines will move accordingly, and stay right at the tips
# of the spines they are 'breaking'
plt.show()