仅删除子图网格中的重叠刻度

时间:2016-06-22 14:00:34

标签: python matplotlib

我创建了一个子图网格,子图之间没有任何空格,共享x,y轴。我只显示外部子图的刻度和标签。问题是刻度数在子图的边界处重叠。使用MaxNLocator,我可以删除上部或下部刻度,但仅适用于所有绘图。

问题:如何仅针对某些图表保留最高刻度(在这种情况下,x = 2.0仅在右下方子图中,而y = 3仅在左上方子图中)?为什么某些子图的刻度条件设置失败?

enter image description here

代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

numPlotsY = 3
numPlotsX = 3
f, ax_grid = plt.subplots(numPlotsY,numPlotsX,sharex=True,sharey=True)

A = np.arange(numPlotsY)+1.0
phi = np.arange(numPlotsX)
x = np.linspace(0,2.0,100)
fontsize = 18

for y_i in range(0,numPlotsY):
    for x_i in range(0,numPlotsX):
        y = A[y_i]*np.sin(x*np.pi + phi[x_i])
        ax = ax_grid[y_i,x_i]
        ax.plot(x,y,lw=2.0)

        if x_i == 0:
            ax.set_ylabel(r'$y$', fontsize=fontsize)

        if y_i == numPlotsY-1:
            ###########################
            # Why doesn't this work?! #
            ###########################
            if x_i != numPlotsX-1:
                nbins = len(ax.get_xticklabels())
                ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='upper'))
            else:
                nbins = len(ax.get_xticklabels())
                ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune=None))
            ax.set_xlabel(r'$x/\pi$', fontsize=fontsize)

        if y_i == 0:
            ax.set_title(r'$\phi=%s$' % phi[x_i], fontsize=fontsize)

        if x_i == numPlotsX-1:
            ax.annotate(r'$A=%d$' % A[x_i], xy=(1.1,0.5), rotation=90,
                        ha='center',va='center',xycoords='axes fraction', fontsize=fontsize)

f.subplots_adjust(wspace=0,hspace=0)
plt.suptitle(r'$A\cdot\sin\left(2\pi x + \phi\right)$',fontsize=18)
plt.show()

1 个答案:

答案 0 :(得分:1)

正如@AndrasDeak指出的那样,只要我设置了sharex = True,sharey = True,我就无法修改单个子图标。 解决方案是将它们设置为false

f, ax_grid = plt.subplots(numPlotsY,numPlotsX,sharex=False,sharey=False)

并将条件语句从原始帖子更改为:

# If left-most column:  Remove all overlapping y-ticks
# Else:                 Remove all ticks
if x_i == 0:
    ax.set_ylabel(r'$y$', fontsize=fontsize)
    # If top left subplot:      Remove bottom y-tick
    # If bottom left subplot:   Remove top y-tick
    # Else:                     Remove top and bottom y-ticks
    if y_i == 0:
        nbins = len(ax.get_yticklabels())
        ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='lower'))
    elif y_i == numPlotsY-1:
        nbins = len(ax.get_yticklabels())
        ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='upper'))
    else:
        nbins = len(ax.get_yticklabels())
        ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='both'))
else:
    ax.yaxis.set_ticks([])

# If bottom row:    Remove all overlapping x-ticks
# Else:             Remove all ticks
if y_i == numPlotsY-1:
    # If bottom left subplot:   Remove right x-tick
    # If bottom right subplot:  Remove top left x-tick
    # Else:                     Remove left and right x-ticks
    if x_i == 0:
        nbins = len(ax.get_xticklabels())
        ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='upper'))
    elif x_i == numPlotsX-1:
        nbins = len(ax.get_xticklabels())
        ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='lower'))
    else:
        nbins = len(ax.get_xticklabels())
        ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='both'))
else:
    ax.xaxis.set_ticks([])

不是最优雅的结果,但它演示了如何仅操纵重叠的刻度: enter image description here

感兴趣的人的完整代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

numPlotsY = 3
numPlotsX = 3
f, ax_grid = plt.subplots(numPlotsY,numPlotsX,sharex=False,sharey=False)

A = np.arange(numPlotsY)+1.0
phi = np.arange(numPlotsX)
x = np.linspace(0,2.0,100)
fontsize = 18

for y_i in range(0,numPlotsY):
    for x_i in range(0,numPlotsX):
        y = A[y_i]*np.sin(x*np.pi + phi[x_i])
        ax = ax_grid[y_i,x_i]
        ax.plot(x,y,lw=2.0)

        # If left-most column:  Remove all overlapping y-ticks
        # Else:                 Remove all ticks
        if x_i == 0:
            ax.set_ylabel(r'$y$', fontsize=fontsize)
            # If top left subplot:      Remove bottom y-tick
            # If bottom left subplot:   Remove top y-tick
            # Else:                     Remove top and bottom y-ticks
            if y_i == 0:
                nbins = len(ax.get_yticklabels())
                ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='lower'))
            elif y_i == numPlotsY-1:
                nbins = len(ax.get_yticklabels())
                ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='upper'))
            else:
                nbins = len(ax.get_yticklabels())
                ax.yaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='both'))
        else:
            ax.yaxis.set_ticks([])

        # If bottom row:    Remove all overlapping x-ticks
        # Else:             Remove all ticks
        if y_i == numPlotsY-1:
            # If bottom left subplot:   Remove right x-tick
            # If bottom right subplot:  Remove top left x-tick
            # Else:                     Remove left and right x-ticks
            if x_i == 0:
                nbins = len(ax.get_xticklabels())
                ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='upper'))
            elif x_i == numPlotsX-1:
                nbins = len(ax.get_xticklabels())
                ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='lower'))
            else:
                nbins = len(ax.get_xticklabels())
                ax.xaxis.set_major_locator(MaxNLocator(nbins=nbins,prune='both'))
        else:
            ax.xaxis.set_ticks([])

        if y_i == 0:
            ax.set_title(r'$\phi=%s$' % phi[x_i], fontsize=fontsize)

        if x_i == numPlotsX-1:
            ax.annotate(r'$A=%d$' % A[x_i], xy=(1.1,0.5), rotation=90,
                        ha='center',va='center',xycoords='axes fraction', fontsize=fontsize)

f.subplots_adjust(wspace=0,hspace=0)
plt.suptitle(r'$A\cdot\sin\left(2\pi x + \phi\right)$',fontsize=18)
plt.show()