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 matplotlib子批次的公共xlabel/ylabel_Python_Matplotlib - Fatal编程技术网

Python matplotlib子批次的公共xlabel/ylabel

Python matplotlib子批次的公共xlabel/ylabel,python,matplotlib,Python,Matplotlib,我有以下情节: fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size) 现在我想给这张图加上普通的x轴和y轴标签。对于“common”,我的意思是在子地块的整个网格下面应该有一个大的x轴标签,在右边应该有一个大的y轴标签。我在plt.subplot的文档中找不到任何关于这方面的信息,我的谷歌搜索结果表明我需要先创建一个大的plt.subplot(111),但是如何使用plt.subplot?将我的5*2子地块放入其

我有以下情节:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)
现在我想给这张图加上普通的x轴和y轴标签。对于“common”,我的意思是在子地块的整个网格下面应该有一个大的x轴标签,在右边应该有一个大的y轴标签。我在
plt.subplot
的文档中找不到任何关于这方面的信息,我的谷歌搜索结果表明我需要先创建一个大的
plt.subplot(111)
,但是如何使用
plt.subplot

将我的5*2子地块放入其中,因为命令:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)
您使用返回一个由图形和轴实例列表组成的元组,这样做已经足够了(请注意,我已将
fig,ax
更改为
fig,axs
):

如果您碰巧想要更改特定子批次的某些详细信息,您可以通过
axes[i]
访问它,其中
i
迭代子批次

包括一个

fig.tight_layout()

在文件末尾,在
plt.show()
之前,为了避免标签重叠。

如果没有
sharex=True,sharey=True
,您会得到:

有了它,你会感觉更好:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))

plt.tight_layout()

但如果要添加其他标签,则应仅将其添加到边缘打印:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))
        if i == len(axes2d) - 1:
            cell.set_xlabel("noise column: {0:d}".format(j + 1))
        if j == 0:
            cell.set_ylabel("noise row: {0:d}".format(i + 1))

plt.tight_layout()


为每个绘图添加标签会破坏它(也许有一种方法可以自动检测重复的标签,但我不知道有一种方法)。

这看起来像是您真正想要的。它将相同的方法应用于您的具体案例:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))

fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')

在绘制图形网格时,我遇到了类似的问题。图表由两部分组成(顶部和底部)。y型标签应该位于两个部分的中心

我不想使用依赖于知道外部图形中的位置的解决方案(如fig.text()),因此我操纵了set_ylabel()函数的y位置。它通常为0.5,即添加到的绘图的中间。由于代码中各部分之间的填充(hspace)为零,因此我可以计算两个部分之间相对于上部的中间部分

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# Create outer and inner grid
outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1])
somePlot = gridspec.GridSpecFromSubplotSpec(2, 1,
               subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0)

# Add two partial plots
partA = plt.subplot(somePlot[0])
partB = plt.subplot(somePlot[1])

# No x-ticks for the upper plot
plt.setp(partA.get_xticklabels(), visible=False)

# The center is (height(top)-height(bottom))/(2*height(top))
# Simplified to 0.5 - height(bottom)/(2*height(top))
mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0])
# Place the y-label
partA.set_ylabel('shared label', y = mid)

plt.show()

缺点:

  • 到绘图的水平距离基于顶部,底部记号可能延伸到标签中

  • 该公式不考虑零件之间的空间

  • 当顶部零件的高度为0时引发异常


可能有一种通用的解决方案考虑到了数字之间的填充。

更新:

这个特性现在是我最近在pypi上发布的特性的一部分。默认情况下,制作图形时,标签在轴之间“共享”


原始答案:

我发现了一种更稳健的方法:

如果您知道进入
GridSpec
初始化的
bottom
top
kwargs,或者您知道
图形
坐标中轴的边位置
,您还可以使用一些奇特的“变换”魔法指定
图形
坐标中的ylabel位置。例如:

import matplotlib.transforms as mtransforms
bottom, top = .1, .9
f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top)
avepos = (bottom+top)/2
a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory(
       mtransforms.IdentityTransform(), f.transFigure # specify x, y transform
       )) # changed from default blend (IdentityTransform(), a[0].transAxes)
a[0].yaxis.label.set_position((0, avepos))
a[0].set_ylabel('Hello, world!')
…您应该看到标签仍然会适当地调整左右以避免与标签重叠,就像正常情况一样--但现在它将调整为始终正好位于所需子批次之间


此外,如果您甚至不使用
set_position
,则默认情况下,ylabel将显示在图形的中间位置。我猜这是因为当最终绘制标签时,
matplotlib
y
-坐标使用0.5,而不检查基础坐标变换是否已更改

如果您为左下角的子地块创建不可见标签,从而为常用标签保留空间,则外观会更好。从rcParams传入fontsize也很好。这样,公共标签的大小将随rc设置而改变,并且轴也将被调整以为公共标签留出空间

fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])

因为我认为它是相关的和优雅的(不需要指定坐标来放置文本),所以我复制(稍加修改)。< /P> 这将产生以下结果(使用matplotlib版本2.2.0):


Matplotlib v3.4中新增的(
pip安装Matplotlib——升级

supxlabelsupylabel

fig.supxlabel('common_x'))
图supylabel('common_y'))
见示例:

导入matplotlib.pyplot作为plt
对于tl,zip中的cl([True,False,False],[False,False,True]):
图=plt.图(约束布局=cl,紧密布局=tl)
gs=图添加网格规格(2,3)
ax=dict()
ax['A']=图add_子图(gs[0,0:2])
ax['B']=图add_子图(gs[1,0:2])
ax['C']=图add_子图(gs[:,2])
ax['C'].setxlabel('Booger'))
ax['B'].setxlabel('Booger'))
ax['A'].set_ylabel('Booger Y'))
图suptitle(f'TEST:tight_布局={tl}约束_布局={cl}'))
图supxlabel('XLAgg')
图supylabel('YLAgg')
plt.show()


很抱歉,我上面有点不清楚。“common”是指所有图下方的一个x标签,以及图左侧的一个y标签,我已经更新了问题以反映这一点。@JohanLindberg:关于您在此处和上方的评论:
plt.subplot()
将创建一个新的地物实例。如果您想继续使用此命令,可以轻松添加一个
big\u ax=fig.add\u子图(111)
,因为您已经有一个图形,可以添加另一个轴。在那之后,你可以按照Hooked链接中显示的方式来操作big_ax。谢谢你的建议,但是如果我这样做,我必须在plt.subplot()之后添加big_ax,然后我将该子图放在其他所有内容之上-我可以使它透明还是以某种方式发送到后面?即使我设定了所有的颜色
fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])
import matplotlib.pyplot as plt
fig, axes = plt.subplots(5, 2, sharex=True, sharey=True, figsize=(6,15))
# add a big axis, hide frame
fig.add_subplot(111, frameon=False)
# hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', which='both', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")