I am unable to successfully plot a 'zoomed' inset with matplotlib.
The x-axis is originally a UTC datetime
column; transformed to count from 0 (zero) and to display: matplotlib.dates
. Ideally I would like the the inset to only show the x-range from 00:30 to 00:45 (h:m) between a y-range of -0.5 to 1 (m). Those fancy lines that link the inset to the main plot would be pretty cool.
My attempt that fails:
import matplotlib.pyplot as plt
import matplotlib.pylab as pl
import matplotlib.dates as md
from mpl_toolkits.axes_grid1.inset_locator import (inset_axes, InsetPosition, mark_inset)
colors = pl.cm.viridis(np.linspace(0,1,3))
# specify a date to use for the times
tdate = df['UTC']-df['UTC'][0]
zero = df['UTC'][0]
time = [zero + t for t in tdate]
# convert datetimes to numbers
zero = md.date2num(zero)
time = [t-zero for t in md.date2num(time)]
fig1 = plt.figure(figsize=(18,12), dpi=80)
fig1.suptitle('Position / Time', fontsize=14, fontweight='bold')
ax = fig1.add_subplot(2,1,1)
names = ['delta y','delta x','delta z']
# Make plots
for i in range(len(names)):
ax.plot(time, df.iloc[:, 19+i], label=names[i], color=colors[i]) #tdate
ax.grid(True)
ax.set_ylabel('Absolute Error (m)')
ax.xaxis_date()
ax.xaxis.set_major_formatter(md.DateFormatter("%H:%M"))
ax.set_xlabel('Time (h:m)')
# Make legend
plt.legend(loc='upper right')
# Create a set of inset Axes
ax2 = plt.axes([100, 500, 0.5, 1])
# Manually set the position and relative size of the inset axes within ax1
ip = InsetPosition(ax, [0.4,0.4,0.5,0.5])
ax2.set_axes_locator(ip)
# do the time for the inset
indate = df[ (df.index >= 1800) & (df.index <= 2700)]
#tdate = df['UTC']-df['UTC'][0]
ztdate = indate['UTC'][2700]-indate['UTC'][1800]
zero = indate['UTC'][1800]
dtime = [zero + t for t in ztdate]
# convert datetimes to numbers
zero = md.date2num(zero)
dtime = [t-zero for t in md.date2num(dtime)]
# plot the inset
for i in range(len(names)):
ax2.plot(dtime, df.iloc[19+i], label=names[i], color=colors[i]) #tdate
#ax2.legend(loc=0)
mark_inset(ax, ax2, loc1=2, loc2=4, fc="none", ec='0.5')
plt.xticks(visible=False)
plt.yticks(visible=False)
ax2.grid(True)
ax2.xaxis_date()
ax2.xaxis.set_major_formatter(md.DateFormatter("%H:%M"))
plt.show()
with the following error message - before it renders the plot above:
Traceback (most recent call last):
File "<ipython-input-18-c3dd5e9ca2b0>", line 45, in <module>
dtime = [zero + t for t in ztdate]
TypeError: 'Timedelta' object is not iterable
DataFrame here . Your help is appreciated.
The key is to trim the time (as a number) and the DataFrame:
t1 = time[1799:3000]
indate = df[(df.index >= 1800) & (df.index <= 3000)]
then with:
import matplotlib.pyplot as plt
import matplotlib.pylab as pl
import matplotlib.dates as md
from mpl_toolkits.axes_grid1.inset_locator import (inset_axes, InsetPosition, mark_inset)
colors = pl.cm.viridis(np.linspace(0,1,3))
# Create a new figure of size 10x6 points, using 80 dots per inch
fig1 = plt.figure(figsize=(18, 12), dpi=80)
fig1.suptitle('Position / Time', fontsize=14, fontweight='bold')
ax = fig1.add_subplot(2,1,1)
names = ['delta y','delta x','delta z']
# specify a date to use for the times
tdate = df['UTC']-df['UTC'][0]
zero = df['UTC'][0]
time = [zero + t for t in tdate]
# convert datetimes to numbers
zero = md.date2num(zero)
time = [t-zero for t in md.date2num(time)]
# Make plots
for i in range(len(names)):
ax.plot(time, df.iloc[:, 19+i], label=names[i], color=colors[i]) #tdate
# Make legend
plt.legend(loc='upper right')
ax.grid(axis='y', linestyle='-', linewidth=0.3)
ax.set_ylabel('Absolute Error (m)')
ax.xaxis_date()
ax.xaxis.set_major_formatter(md.DateFormatter("%H:%M"))
ax.set_xlabel('Time (h:m)')
# Make legend
plt.legend(loc='upper right')
# Create a set of inset Axes
ax2 = plt.axes([0, 0, 1, 1])
# Manually set the position and relative size of the inset axes within ax1
ip = InsetPosition(ax, [0.4,0.4,0.5,0.5])
ax2.set_axes_locator(ip)
# do the time for the inset
t1 = time[1799:3000]
indate = df[(df.index >= 1800) & (df.index <= 3000)]
# plot the inset
for i in range(len(names)):
ax2.plot(t1, indate.iloc[:, 19+i], color=colors[i])#label=names[i]) #tdate
# -- https://stackoverflow.com/questions/44715968/matplotlib-change-style-of-inset-elements-singularly
plt.setp(list(ax2.spines.values()), linewidth=0.5, linestyle="--")
box, c1, c2 = mark_inset(ax, ax2, loc1=2, loc2=3, fc="none", lw=0.3, ec='0.5')
plt.setp([c1,c2], linestyle=":")
ax2.grid(axis='y', linestyle='-') #True
ax2.xaxis_date()
ax2.xaxis.set_major_formatter(md.DateFormatter("%H:%M"))
plt.show()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.