【问题标题】:matplotlib inset with '%H:%M' x-axismatplotlib inset with '%H:%M' x 轴
【发布时间】:2021-12-15 13:27:49
【问题描述】:

我无法使用 matplotlib 成功绘制 'zoomed' 插图。

x轴原来是UTC datetime列;转换为从 0(零)开始计数并显示:matplotlib.dates。理想情况下,我希望插图仅显示从 00:30 到 00:45 (h:m) 的 x 范围,介于 -0.5 到 1 (m) 的 y 范围之间。那些将插图与主要情节联系起来的花哨的线条会很酷。

我的尝试失败了:

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()

带有以下错误消息 - 在呈现上面的图之前:

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

数据帧here。感谢您的帮助。

【问题讨论】:

  • 这不是 matplotlib 问题。您的变量 ztdateTimedelta,其计算结果显示错误上方 2 行。
  • 也许你想要ztdate = indate['UTC']-indate['UTC'][1800]
  • 在该循环之前检查dtime 的值。我不认为dtime = [t-zero for t in md.date2num(dtime)] 正在做你想做的事。
  • 感谢@Riley 的快速回复。现在:TypeError: 'value' must be an instance of str or bytes, not a pandas._libs.tslibs.timestamps.Timestamp# plot the inset...
  • 查看您的dtime 的价值。错误是说它是Timestamp。您似乎希望它是一个数字。

标签: python pandas datetime matplotlib


【解决方案1】:

关键是修剪时间(作为数字)和DataFrame:

t1 = time[1799:3000]
indate = df[(df.index >= 1800) & (df.index <= 3000)] 

然后用:

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()

结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-10
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2016-06-22
    • 2013-01-15
    • 2012-09-07
    相关资源
    最近更新 更多