如何在python matplotlib中添加第三级刻度 [英] How to add third level of ticks in python matplotlib
问题描述
Matplotlib 轴有主要和次要刻度.如何在 Minor 下方添加第三个刻度?
例如
将matplotlib.pyplot导入为plt将numpy导入为np导入 matplotlib.tickert = np.arange(0.0,100.0,0.1)s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)无花果,ax = plt.subplots()plt.plot(t, s)ax1 = ax.twiny()ax1.plot(t, s)ax1.xaxis.set_ticks_position('底部')专业 = np.linspace(0, 100, 6)未成年人 = np.linspace(0, 100, 11)三分之二= np.linspace(0,100,101)ax.xaxis.set_major_locator(matplotlib.ticker.FixedLocator(majors))ax.xaxis.set_minor_locator(matplotlib.ticker.FixedLocator(未成年人))ax1.xaxis.set_major_locator(matplotlib.ticker.FixedLocator([]))ax1.xaxis.set_minor_locator(matplotlib.ticker.FixedLocator(thirds))ax1.tick_params(which='minor', length=2)ax.tick_params(which='minor', length=4)ax.tick_params(which ='major',length = 6)ax.grid(which ='both',axis ='x',linestyle ='-')plt.axhline(颜色='灰色')plt.show()
使用孪生 x 轴产生我想要的效果.
有更好的方法吗?
正如我所说的那样,您可以通过从某些关键类中派生来实现所需的功能,所以我决定这样做(但正如我所说,这可能不值得努力).无论如何,这就是我所拥有的:
from matplotlib import pyplot as plt从matplotlib导入轴作为maxes从 matplotlib 导入轴作为 maxis导入 matplotlib.ticker 作为 mticker将 matplotlib.cbook 导入为 cbook从 matplotlib.projections 导入 register_projection从matplotlib导入代码将numpy导入为npSubMinorXAxis(maxis.XAxis)类:def __init__(self,*args,**kwargs):self.subminor = maxis.Ticker()self.subminorTicks = []self._subminor_tick_kw = dict()super(SubMinorXAxis,self).__ init __(* args,** kwargs)def reset_ticks():cbook.popall(self.subminorTicks)## self.subminorTicks.extend([self._get_tick(major = False)])self.subminorTicks.extend([maxis.XTick(self.axes,0,'',major = False,** self._subminor_tick_kw)])self._lastNumSubminorTicks = 1超级(SubMinorXAxis,self).reset_ticks()def set_subminor_locator(self, locator):"""设置次要代码的定位器接受:一个 :class:`~matplotlib.ticker.Locator` 实例"""self.isDefault_minloc = Falseself.subminor.locator = 定位器locator.set_axis()self.stale = Truedef set_subminor_formatter(self,formatter):"""设置 subminor 代码的格式化程序接受:一个 :class:`~matplotlib.ticker.Formatter` 实例"""self.isDefault_minfmt = Falseself.subminor.formatter =格式化程序formatter.set_axis()self.stale = Truedef get_subminor_ticks(self,numticks = None):'获取次要壁虱实例;根据需要增长'如果 numticks 为 None:numticks = len(self.get_subminor_locator()())如果 len(self.subminorTicks)
它并不完美,但对于您提供的用例,它工作正常.我从
我在Python 2.7和Python 3.5上都测试了代码.
编辑:
我注意到 subminor
网格线将始终在网格打开的情况下绘制(尽管我原本打算完全不绘制).我已在上面的代码中对此进行了更正,即 subminor
刻度永远不会产生网格线.如果要正确实施网格线,还需要做更多的工作.
Matplotlib axes have Major and Minor ticks. How do I add a third level of tick below Minor?
For example
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker
t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)
fig, ax = plt.subplots()
plt.plot(t, s)
ax1 = ax.twiny()
ax1.plot(t, s)
ax1.xaxis.set_ticks_position('bottom')
majors = np.linspace(0, 100, 6)
minors = np.linspace(0, 100, 11)
thirds = np.linspace(0, 100, 101)
ax.xaxis.set_major_locator(matplotlib.ticker.FixedLocator(majors))
ax.xaxis.set_minor_locator(matplotlib.ticker.FixedLocator(minors))
ax1.xaxis.set_major_locator(matplotlib.ticker.FixedLocator([]))
ax1.xaxis.set_minor_locator(matplotlib.ticker.FixedLocator(thirds))
ax1.tick_params(which='minor', length=2)
ax.tick_params(which='minor', length=4)
ax.tick_params(which='major', length=6)
ax.grid(which='both',axis='x',linestyle='--')
plt.axhline(color='gray')
plt.show()
produces the effect I want using twinned x-axes.
Is there a better way?
As I stated that you can achieve what you want by deriving from some key classes, I decided to do so (but as I said, it's probably not worth the effort). Anyway, here is what I've got:
from matplotlib import pyplot as plt
from matplotlib import axes as maxes
from matplotlib import axis as maxis
import matplotlib.ticker as mticker
import matplotlib.cbook as cbook
from matplotlib.projections import register_projection
from matplotlib import ticker
import numpy as np
class SubMinorXAxis(maxis.XAxis):
def __init__(self,*args,**kwargs):
self.subminor = maxis.Ticker()
self.subminorTicks = []
self._subminor_tick_kw = dict()
super(SubMinorXAxis,self).__init__(*args,**kwargs)
def reset_ticks(self):
cbook.popall(self.subminorTicks)
##self.subminorTicks.extend([self._get_tick(major=False)])
self.subminorTicks.extend([maxis.XTick(self.axes, 0, '', major=False, **self._subminor_tick_kw)])
self._lastNumSubminorTicks = 1
super(SubMinorXAxis,self).reset_ticks()
def set_subminor_locator(self, locator):
"""
Set the locator of the subminor ticker
ACCEPTS: a :class:`~matplotlib.ticker.Locator` instance
"""
self.isDefault_minloc = False
self.subminor.locator = locator
locator.set_axis(self)
self.stale = True
def set_subminor_formatter(self, formatter):
"""
Set the formatter of the subminor ticker
ACCEPTS: A :class:`~matplotlib.ticker.Formatter` instance
"""
self.isDefault_minfmt = False
self.subminor.formatter = formatter
formatter.set_axis(self)
self.stale = True
def get_subminor_ticks(self, numticks=None):
'get the subminor tick instances; grow as necessary'
if numticks is None:
numticks = len(self.get_subminor_locator()())
if len(self.subminorTicks) < numticks:
# update the new tick label properties from the old
for i in range(numticks - len(self.subminorTicks)):
##tick = self._get_tick(major=False)
tick = maxis.XTick(self.axes, 0, '', major=False, **self._subminor_tick_kw)
self.subminorTicks.append(tick)
if self._lastNumSubminorTicks < numticks:
protoTick = self.subminorTicks[0]
for i in range(self._lastNumSubminorTicks, len(self.subminorTicks)):
tick = self.subminorTicks[i]
tick.gridOn = False
self._copy_tick_props(protoTick, tick)
self._lastNumSubminorTicks = numticks
ticks = self.subminorTicks[:numticks]
return ticks
def set_tick_params(self, which='major', reset=False, **kwargs):
if which == 'subminor':
kwtrans = self._translate_tick_kw(kwargs, to_init_kw=True)
if reset:
self.reset_ticks()
self._subminor_tick_kw.clear()
self._subminor_tick_kw.update(kwtrans)
for tick in self.subminorTicks:
tick._apply_params(**self._subminor_tick_kw)
else:
super(SubMinorXAxis, self).set_tick_params(which=which, reset=reset, **kwargs)
def cla(self):
'clear the current axis'
self.set_subminor_locator(mticker.NullLocator())
self.set_subminor_formatter(mticker.NullFormatter())
super(SubMinorXAxis,self).cla()
def iter_ticks(self):
"""
Iterate through all of the major and minor ticks.
...and through the subminors
"""
majorLocs = self.major.locator()
majorTicks = self.get_major_ticks(len(majorLocs))
self.major.formatter.set_locs(majorLocs)
majorLabels = [self.major.formatter(val, i)
for i, val in enumerate(majorLocs)]
minorLocs = self.minor.locator()
minorTicks = self.get_minor_ticks(len(minorLocs))
self.minor.formatter.set_locs(minorLocs)
minorLabels = [self.minor.formatter(val, i)
for i, val in enumerate(minorLocs)]
subminorLocs = self.subminor.locator()
subminorTicks = self.get_subminor_ticks(len(subminorLocs))
self.subminor.formatter.set_locs(subminorLocs)
subminorLabels = [self.subminor.formatter(val, i)
for i, val in enumerate(subminorLocs)]
major_minor = [
(majorTicks, majorLocs, majorLabels),
(minorTicks, minorLocs, minorLabels),
(subminorTicks, subminorLocs, subminorLabels),
]
for group in major_minor:
for tick in zip(*group):
yield tick
class SubMinorAxes(maxes.Axes):
name = 'subminor'
def _init_axis(self):
self.xaxis = SubMinorXAxis(self)
self.spines['top'].register_axis(self.xaxis)
self.spines['bottom'].register_axis(self.xaxis)
self.yaxis = maxis.YAxis(self)
self.spines['left'].register_axis(self.yaxis)
self.spines['right'].register_axis(self.yaxis)
register_projection(SubMinorAxes)
if __name__ == '__main__':
fig = plt.figure()
ax = fig.add_subplot(111,projection = 'subminor')
t = np.arange(0.0, 100.0, 0.1)
s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)
majors = np.linspace(0, 100, 6)
minors = np.linspace(0, 100, 11)
thirds = np.linspace(0, 100, 101)
ax.plot(t, s)
ax.xaxis.set_ticks_position('bottom')
ax.xaxis.set_major_locator(ticker.FixedLocator(majors))
ax.xaxis.set_minor_locator(ticker.FixedLocator(minors))
ax.xaxis.set_subminor_locator(ticker.FixedLocator(thirds))
##some things in set_tick_params are not being set correctly
##by default. For instance 'top=False' must be stated
##explicitly
ax.tick_params(which='subminor', length=2, top=False)
ax.tick_params(which='minor', length=4)
ax.tick_params(which='major', length=6)
ax.grid(which='both',axis='x',linestyle='--')
plt.show()
It's not perfect, but for the use case you provided it's working fine. I drew some ideas from this matplotlib example and by going through the source codes directly. The result looks like this:
I tested the code on both Python 2.7 and Python 3.5.
EDIT:
I noticed that the subminor
gridlines would always be drawn if the grid is turned on (while I had intended for it not to be drawn at all). I rectified this in the code above, i.e. the subminor
ticks should never produce grid lines. If gridlines should be implemented properly, some more work will be needed.
这篇关于如何在python matplotlib中添加第三级刻度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!