我正在尝试生成一个 matplotlib 图,该图由两个共享 x 轴的子图组成。一个子图在不同的 y 轴刻度上绘制两组数据,另一个子图仅绘制一组数据。
我还想“打破”两个子图的 x 轴,以说明我的数据测量之间的很长一段时间。
我已经尝试使用这篇文章中提出的解决方案,但正如一位海报所声称的那样,这种方法不能正确缩放子图 x 轴。
我一直在尝试使用brokenaxes包。它似乎创建了多个子图,相应地缩放它们,并自动隐藏无关的刺、刻度和刻度标签。这个包似乎不支持sharex
与从 GridSpec 创建的子图共享 x 轴 ( )。此外,该方法twinx
本身不适用于断轴对象。但是,每个折轴对象都包含一个子图轴对象列表。每个轴对象都可用于生成一个twinx
,尽管这会导致 matplotlib 重新缩放子图、重绘脊椎、刻度线和标签。
我试图手动隐藏所有重绘的元素,但是我仍然遇到一些问题。
- 表示断轴的线放置在不正确的位置
- 我在右上角的子图上留下了无法隐藏的 y 轴刻度线
- 右上角子图上的网格线不正确,并且与底部子图上的 x 轴不一致。
- 我想使用
'%m-%d'
用于 x 轴刻度的日期格式化程序,但尝试它时出错:
AttributeError: 'CallCurator' object has no attribute 'set_major_formatter
以及用于生成它的腌制熊猫数据和代码:
#!/usr/bin/env python3
import matplotlib as mpl
font= {'family': 'Arial',
'size': 7}
mpl.rc('font', **font)
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from matplotlib.ticker import NullFormatter
import matplotlib.dates as md
from brokenaxes import brokenaxes
import datetime
from pytz import timezone
import numpy as np
from pytz import timezone
import pandas as pd
from glob import glob
volt_color= 'tab:blue'
volt_style = 'solid'
amp_color = 'tab:red'
amp_style='dashed'
# starting date
start = pd.to_datetime("2020-05-20 15:40:09.059089184-07:00", infer_datetime_format=True).to_pydatetime()
start = timezone('US/Pacific').localize(start)
# load data
mudbat_data = pd.read_pickle("mudbat_data.pkl")
# perform rolling mean over data
mv = mudbat_data.rolling(5*60).mean()
# instantiate figures, and broken axes subplots
fig = plt.figure(figsize=(4,2))
gs = GridSpec(2,1)
tz = timezone('US/Pacific')
print(start)
[x1, x2, x3, x4] = [start, datetime.datetime(2020,5,27,tzinfo=tz), datetime.datetime(2020,7,20,tzinfo=tz),datetime.datetime(2020,7,22,tzinfo=tz)]
bax1 = brokenaxes(xlims=((x1,x2),(x3,x4)), subplot_spec=gs[0])
bax3 = brokenaxes(xlims=((x1,x2),(x3,x4)), subplot_spec=gs[1])
# plot first data
bax1.set_ylabel('Cell Voltage (V)')
bax1.plot(mv.index, mv['voltage'], color=volt_color, ls=volt_style)
bax1.tick_params(axis='y', labelcolor=volt_color)
bax1.grid(True)
# ensure all extraneous ticks for bax1 are hidden
bax1.axs[0].yaxis.tick_left()
bax1.axs[0].xaxis.set_ticklabels([])
bax1.axs[0].xaxis.set_ticklabels([])
bax1.axs[0].xaxis.set_ticks_position('none')
bax1.axs[0].yaxis.set_ticks_position('none')
bax1.axs[1].xaxis.set_ticklabels([])
bax1.axs[1].yaxis.set_ticklabels([])
bax1.axs[1].xaxis.set_ticks_position('none')
bax1.axs[1].yaxis.set_ticks_position('none')
# generate bax2 from bax1 axes
bax2 = []
for ax in bax1.axs:
bax2.append(ax.twinx())
# plot data on bax2 subplots
bax2[0].plot(mv.index, -1E6*mv['current'], color=amp_color, ls=amp_style)
bax2[1].plot(mv.index, -1E6*mv['current'], color=amp_color, ls=amp_style)
bax2[1].set_ylabel('Harvesting Current (μA)')
bax2[1].tick_params(axis='y', labelcolor=amp_color)
# hide generated spines and ticks/labels
bax2[0].spines['right'].set_visible(False)
bax2[0].yaxis.set_ticklabels([])
bax2[0].xaxis.set_ticklabels([])
bax2[0].xaxis.set_ticks_position('none')
bax2[0].yaxis.set_ticks_position('none')
bax2[1].spines['left'].set_visible(False)
bax2[1].xaxis.set_ticklabels([])
bax2[1].xaxis.set_ticks_position('none')
bax2[1].yaxis.tick_right()
# I would like to use this formatter
#bax3.xaxis.set_major_formatter(md.DateFormatter('%m-%d'))
bax3.set_ylabel("Power (uW)")
bax3.grid(True)
bax3.plot(mv.index, 1E6*mv['power'])
bax3.tick_params(axis='x', labelsize=6, rotation=45)
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5)
plt.subplots_adjust(hspace=0)
plt.savefig('plot.png', dpi=300)
感谢您提供的任何帮助或建议!