简体   繁体   中英

Change axis line range in mpl_toolkits new_fixed_axis

I am struggling to modify my code to define a specific range of the secondary x-axis. Below is a snippet of the relevant code for creating 2 x-axes, and the output it generates:

from matplotlib import pyplot as plt
import matplotlib.ticker as ticker
from mpl_toolkits.axes_grid.parasite_axes import SubplotHost

...
    x = np.arange(1, len(metric1)+1)  # the label locations
    width = 0.3  # the width of the bars

    fig1 = plt.figure()
    ax1 = SubplotHost(fig1, 111)
    fig1.add_subplot(ax1)
    ax1.axis((0, 14, 0, 20))
    ax1.bar(x, [t[2] for t in metric1], width, label='metric1')
    ax1.bar(x + width, [t[2] for t in metric2], width, label='metric2')
    ax1.bar(x + 2*width, [t[2] for t in metric3], width, label='metric3')

    ax1.set_xticks(x+width)
    ax1.set_xticklabels(['BN', 'B', 'DO', 'N', 'BN', 'B', 'DO', 'N', 'BN', 'B', 'DO', 'N', 'BN', 'B', 'DO', 'N'])
    ax1.axis["bottom"].major_ticks.set_ticksize(0)
    ax2 = ax1.twiny()
    offset = 0, -25 # Position of the second axis
    new_axisline = ax2.get_grid_helper().new_fixed_axis
    ax2.axis["bottom"] = new_axisline(loc="bottom", axes=ax2, offset=offset)
    ax2.axis["top"].set_visible(False)
    ax2.axis["bottom"].minor_ticks.set_ticksize(0)
    ax2.axis["bottom"].major_ticks.set_ticksize(15)

    ax2.set_xticks([0.058, 0.3434, 0.63, 0.915])
    ax2.xaxis.set_major_formatter(ticker.NullFormatter())
    ax2.xaxis.set_minor_locator(ticker.FixedLocator([0.20125, 0.48825, 0.776]))
    ax2.xaxis.set_minor_formatter(ticker.FixedFormatter(['foo', 'bar', 'foo2']))
...

This is the current output:

这是当前输出

What I would like to have, is to not have the secondary x-axis (foo, bar, foo2) line extend beyond the first and last x-tick, as follows (I edited in MS paint ):

在此处输入图像描述

Any help appreciated.

As there have been no other answers, I can suggest a non-elegant way of doing what you need.

You can hide the axis line and "manually" create one line yourself:

import matplotlib.lines as lines

ax2.axis["bottom"].line.set_visible(False)

p1 = ax2.axis["bottom"].line.get_extents().get_points()

x1 = 0.058 * (p1[1][0]-p1[0][0]) / (1) + p1[0][0]
x2 = 0.915 * (p1[1][0]-p1[0][0]) / (1) + p1[0][0]

newL = lines.Line2D([x1,x2], [p1[0][1],p1[1][1]], transform=None, axes=ax2,color="k",linewidth=0.5)
ax2.lines.extend([newL,])

Which gives, in a simple example, something like this: 在此处输入图像描述

As opposed to:

在此处输入图像描述

Alternative

One alternative for the creation of multiple axis is using spines (no parasite axis): https://matplotlib.org/stable/gallery/ticks_and_spines/multiple_yaxis_with_spines.html

In this case, it is possible to do what you need simply by changing the bounds of the spines. For instance, by adding the following line to the code in the link

par2.spines["right"].set_bounds(10,30)

we get this:

在此处输入图像描述

Obviously, this does not strictly reply to the title of your question, and unfortunately, I do not know a proper way of doing it for new_fixed_axis as it can be done for the spines. I hope the "manually" created line solves your issue, in case nobody else comes with a better solution.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM