Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 子地块的pyplot轴标签_Python_Matplotlib_Label_Subplot_Axes - Fatal编程技术网

Python 子地块的pyplot轴标签

Python 子地块的pyplot轴标签,python,matplotlib,label,subplot,axes,Python,Matplotlib,Label,Subplot,Axes,我有以下情节: import matplotlib.pyplot as plt fig2 = plt.figure() ax3 = fig2.add_subplot(2,1,1) ax4 = fig2.add_subplot(2,1,2) ax4.loglog(x1, y1) ax3.loglog(x2, y2) ax3.set_ylabel('hello') 我希望能够创建轴标签和标题,不仅是为两个子地块中的每一个子地块创建,还为跨越两个子地块的公共标签创建。例如,因为两个图都有相同的轴,

我有以下情节:

import matplotlib.pyplot as plt

fig2 = plt.figure()
ax3 = fig2.add_subplot(2,1,1)
ax4 = fig2.add_subplot(2,1,2)
ax4.loglog(x1, y1)
ax3.loglog(x2, y2)
ax3.set_ylabel('hello')
我希望能够创建轴标签和标题,不仅是为两个子地块中的每一个子地块创建,还为跨越两个子地块的公共标签创建。例如,因为两个图都有相同的轴,所以我只需要一组x轴和y轴标签。不过,我确实希望每个子地块有不同的标题


我尝试了一些方法,但没有一种是正确的

您可以创建一个覆盖两个子地块的大子地块,然后设置公共标签

随机导入
将matplotlib.pyplot作为plt导入
x=范围(1101)
y1=[random.randint(1100)表示范围内(len(x))]
y2=[random.randint(1100)表示范围内(len(x))]
图=plt.图()
ax=图添加_子图(111)#大子图
ax1=图添加子批次(211)
ax2=图添加子批次(212)
#关闭大子地块的轴线和记号
斧头刺['top'].设置颜色(“无”)
斧头刺['bottom'].设置颜色('none')
斧头刺['left'].设置颜色(“无”)
斧头刺['right'].设置颜色('none')
ax.tick_参数(labelcolor='w',top=False,bottom=False,left=False,right=False)
ax1.日志日志(x,y1)
ax2.loglog(x,y2)
#设置通用标签
ax.set_xlabel('common xlabel'))
ax.set_ylabel('common ylabel'))
ax1.设置标题(“ax1标题”)
ax2.设置标题(“ax2标题”)
plt.savefig('common_labels.png',dpi=300)

另一种方法是使用fig.text()直接设置常用标签的位置

随机导入
将matplotlib.pyplot作为plt导入
x=范围(1101)
y1=[random.randint(1100)表示范围内(len(x))]
y2=[random.randint(1100)表示范围内(len(x))]
图=plt.图()
ax1=图添加子批次(211)
ax2=图添加子批次(212)
ax1.日志日志(x,y1)
ax2.loglog(x,y2)
#设置通用标签
图文本(0.5,0.04,'通用xlabel',ha='center',va='center')
图文本(0.06,0.5,'公共标签',ha='中间',va='中间',旋转='垂直')
ax1.设置标题(“ax1标题”)
ax2.设置标题(“ax2标题”)
plt.savefig('common_labels_text.png',dpi=300)

如果您不想导出矢量图形,或者您已经将matplotlib后端设置为忽略无色轴,那么廖文伟的答案是好的;否则,隐藏的轴将显示在导出的图形中

我在这里的回答类似于使用
fig.text
功能的
fig.suptitle
。因此,没有任何艺术家被创造出来,并使其无色。 但是,如果您多次尝试调用它,您将得到一个又一个添加的文本(正如
fig.suptitle
所做的那样)。廖文伟的答案是否定的,因为
fig.add_子图(111)
将返回相同的Axes对象(如果已经创建)

也可以在创建绘图后调用My函数

def suplabel(axis,label,label_prop=None,
             labelpad=5,
             ha='center',va='center'):
    ''' Add super ylabel or xlabel to the figure
    Similar to matplotlib.suptitle
    axis       - string: "x" or "y"
    label      - string
    label_prop - keyword dictionary for Text
    labelpad   - padding from the axis (default: 5)
    ha         - horizontal alignment (default: "center")
    va         - vertical alignment (default: "center")
    '''
    fig = pylab.gcf()
    xmin = []
    ymin = []
    for ax in fig.axes:
        xmin.append(ax.get_position().xmin)
        ymin.append(ax.get_position().ymin)
    xmin,ymin = min(xmin),min(ymin)
    dpi = fig.dpi
    if axis.lower() == "y":
        rotation=90.
        x = xmin-float(labelpad)/dpi
        y = 0.5
    elif axis.lower() == 'x':
        rotation = 0.
        x = 0.5
        y = ymin - float(labelpad)/dpi
    else:
        raise Exception("Unexpected axis: x or y")
    if label_prop is None: 
        label_prop = dict()
    pylab.text(x,y,label,rotation=rotation,
               transform=fig.transFigure,
               ha=ha,va=va,
               **label_prop)

使用
子地块的一种简单方法是:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(3, 4, sharex=True, sharey=True)
# add a big axes, hide frame
fig.add_subplot(111, frameon=False)
# hide tick and tick label of the big axes
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.grid(False)
plt.xlabel("common X")
plt.ylabel("common Y")

这里是一个解决方案,您可以设置其中一个绘图的ylabel,并调整其位置,使其垂直居中。这样可以避免KYC提到的问题

import numpy as np
import matplotlib.pyplot as plt

def set_shared_ylabel(a, ylabel, labelpad = 0.01):
    """Set a y label shared by multiple axes
    Parameters
    ----------
    a: list of axes
    ylabel: string
    labelpad: float
        Sets the padding between ticklabels and axis label"""

    f = a[0].get_figure()
    f.canvas.draw() #sets f.canvas.renderer needed below

    # get the center position for all plots
    top = a[0].get_position().y1
    bottom = a[-1].get_position().y0

    # get the coordinates of the left side of the tick labels 
    x0 = 1
    for at in a:
        at.set_ylabel('') # just to make sure we don't and up with multiple labels
        bboxes, _ = at.yaxis.get_ticklabel_extents(f.canvas.renderer)
        bboxes = bboxes.inverse_transformed(f.transFigure)
        xt = bboxes.x0
        if xt < x0:
            x0 = xt
    tick_label_left = x0

    # set position of label
    a[-1].set_ylabel(ylabel)
    a[-1].yaxis.set_label_coords(tick_label_left - labelpad,(bottom + top)/2, transform=f.transFigure)

length = 100
x = np.linspace(0,100, length)
y1 = np.random.random(length) * 1000
y2 = np.random.random(length)

f,a = plt.subplots(2, sharex=True, gridspec_kw={'hspace':0})
a[0].plot(x, y1)
a[1].plot(x, y2)
set_shared_ylabel(a, 'shared y label (a. u.)')
将numpy导入为np
将matplotlib.pyplot作为plt导入
def set_shared_ylabel(a,ylabel,labelpad=0.01):
“”“设置由多个轴共享的y标签
参数
----------
a:轴列表
伊拉贝尔:字符串
标签板:浮动
设置标签和轴标签“”之间的填充
f=a[0]。获取图()
f、 canvas.draw()#设置下面需要的f.canvas.renderer
#获取所有绘图的中心位置
top=a[0]。获取位置().y1
bottom=a[-1]。获取位置().y0
#获取刻度标签左侧的坐标
x0=1
对于a中的at:
at.set_ylabel(“”)#只是为了确保我们不使用多个标签
bboxes,=at.yaxis.get_ticklab_区段(f.canvas.renderer)
B盒=B盒。逆_变换(f.变换)
xt=bboxes.x0
如果xt

当Ytick较大时,其他答案中的方法将无法正常工作。ylabel要么与记号重叠,要么被剪裁在左侧,要么完全不可见/位于图形外部

我修改了Hagne的答案,因此它可以处理超过1列的子图,对于xlabel和ylabel,并且它会移动绘图以保持ylabel在图中可见

def set_shared_ylabel(a, xlabel, ylabel, labelpad = 0.01, figleftpad=0.05):
    """Set a y label shared by multiple axes
    Parameters
    ----------
    a: list of axes
    ylabel: string
    labelpad: float
        Sets the padding between ticklabels and axis label"""

    f = a[0,0].get_figure()
    f.canvas.draw() #sets f.canvas.renderer needed below

    # get the center position for all plots
    top = a[0,0].get_position().y1
    bottom = a[-1,-1].get_position().y0

    # get the coordinates of the left side of the tick labels
    x0 = 1
    x1 = 1
    for at_row in a:
        at = at_row[0]
        at.set_ylabel('') # just to make sure we don't and up with multiple labels
        bboxes, _ = at.yaxis.get_ticklabel_extents(f.canvas.renderer)
        bboxes = bboxes.inverse_transformed(f.transFigure)
        xt = bboxes.x0
        if xt < x0:
            x0 = xt
            x1 = bboxes.x1
    tick_label_left = x0

    # shrink plot on left to prevent ylabel clipping
    # (x1 - tick_label_left) is the x coordinate of right end of tick label,
    # basically how much padding is needed to fit tick labels in the figure
    # figleftpad is additional padding to fit the ylabel
    plt.subplots_adjust(left=(x1 - tick_label_left) + figleftpad)

    # set position of label, 
    # note that (figleftpad-labelpad) refers to the middle of the ylabel
    a[-1,-1].set_ylabel(ylabel)
    a[-1,-1].yaxis.set_label_coords(figleftpad-labelpad,(bottom + top)/2, transform=f.transFigure)

    # set xlabel
    y0 = 1
    for at in axes[-1]:
        at.set_xlabel('')  # just to make sure we don't and up with multiple labels
        bboxes, _ = at.xaxis.get_ticklabel_extents(fig.canvas.renderer)
        bboxes = bboxes.inverse_transformed(fig.transFigure)
        yt = bboxes.y0
        if yt < y0:
            y0 = yt
    tick_label_bottom = y0

    axes[-1, -1].set_xlabel(xlabel)
    axes[-1, -1].xaxis.set_label_coords((left + right) / 2, tick_label_bottom - labelpad, transform=fig.transFigure)

或者,如果你对无色轴没问题,我已经修改了Julian Chen的解决方案,这样ylabel就不会与记号标签重叠

基本上,我们只需要设置无色的ylims,这样它就可以匹配子批次中最大的ylims,这样无色的记号标签就可以为ylabel设置正确的位置

同样,我们必须缩小绘图以防止剪切。在这里,我已经硬编码了要缩小的数量,但是你可以四处寻找一个适合你的数字,或者像上面的方法一样计算它

import matplotlib.pyplot as plt
import itertools

fig, axes = plt.subplots(3, 4, sharey='row', sharex=True, squeeze=False)
fig.subplots_adjust(hspace=.5)
miny = maxy = 0
for i, a in enumerate(itertools.chain(*axes)):
    a.plot([0,4**i], [0,4**i])
    a.set_title(i)
    miny = min(miny, a.get_ylim()[0])
    maxy = max(maxy, a.get_ylim()[1])

# add a big axes, hide frame
# set ylim to match the largest range of any subplot
ax_invis = fig.add_subplot(111, frameon=False)
ax_invis.set_ylim([miny, maxy])

# hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")

# shrink plot to prevent clipping
plt.subplots_adjust(left=0.15)
plt.show()
plt.setp()
将完成以下工作:

# plot something
fig, axs = plt.subplots(3,3, figsize=(15, 8), sharex=True, sharey=True)
for i, ax in enumerate(axs.flat):
    ax.scatter(*np.random.normal(size=(2,200)))
    ax.set_title(f'Title {i}')

# set labels
plt.setp(axs[-1, :], xlabel='x axis label')
plt.setp(axs[:, 0], ylabel='y axis label')


suptitle函数使用fig.text()版本。因此,这可能是一种“官方”的方法?值得强调的是,必须在
ax1
ax2
之前创建
ax
,否则大图将掩盖小图。如果全局打印参数包括(可见),则还需要ax.grid(False)或plt.grid(False)网格。第一种方法似乎不再适用于matplotplib的最新版本(我使用2.0.2):添加到封闭轴的标签不可见。如何将y_标签添加到每个单独的子地块?如果全局打印参数包括(可见)网格,则还需要ax.grid(False)或plt.grid(False)。我这样做是为了(5,1)子地块和我的ylabel在
# list loss and acc are your data
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot(iteration1, loss)
ax2.plot(iteration2, acc)

ax1.set_title('Training Loss')
ax2.set_title('Training Accuracy')

ax1.set_xlabel('Iteration')
ax1.set_ylabel('Loss')

ax2.set_xlabel('Iteration')
ax2.set_ylabel('Accuracy')
# plot something
fig, axs = plt.subplots(3,3, figsize=(15, 8), sharex=True, sharey=True)
for i, ax in enumerate(axs.flat):
    ax.scatter(*np.random.normal(size=(2,200)))
    ax.set_title(f'Title {i}')

# set labels
plt.setp(axs[-1, :], xlabel='x axis label')
plt.setp(axs[:, 0], ylabel='y axis label')