【问题标题】:matplotlib: axes border and tick mark/label locationsmatplotlib:轴边框和刻度线/标签位置
【发布时间】:2019-05-21 02:29:13
【问题描述】:

我试图达到的最终结果是在我的地块周围有一个“更厚”的黑色边框,沿着 xmin、xmax、ymin 和 ymax。我尝试了几种不同的方法(例如仅在绘图上绘制一个矩形,见下文),但由于某些原因,我无法达到预期的结果。

因为我不能只使用刺(我将其中的 2 个设置为始终为 0),所以我需要添加一些其他线条或矩形来创建所需的边框。

默认情况下,第一个和最后一个刻度标签悬在轴上。我通过改变水平或垂直对齐方式“克服”了这一点,但他们仍然可以使用更多的填充。我知道这是可能的,但需要转换并且有点笨重。

现在我想删除两个轴上的第一个和最后一个刻度线。这是因为考虑到矩形的绘制方式,它总是在绘图区域内,但第一个和最后一个刻度线总是在它之外,不管矩形有多厚。使矩形变粗只会使其与第一个和最后一个刻度标签重叠更多,实际的刻度线仍然在矩形之外。

欢迎任何其他关于如何实现这种边界同时始终将轴保持在 0、0 的建议。这就是总体期望的结果。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.patches import Rectangle

X = np.random.randint(low=-9, high=9, size=10)
Y = np.random.randint(low=-9, high=9, size=10)

fig, ax = plt.subplots()
ax.axis([-10, 10, -10, 10])
ax.spines['left'].set_position('zero')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.setp(ax.xaxis.get_majorticklabels()[0], ha='left')
plt.setp(ax.xaxis.get_majorticklabels()[-1], ha='right')
plt.setp(ax.yaxis.get_majorticklabels()[0], va='bottom')
plt.setp(ax.yaxis.get_majorticklabels()[-1], va='top')
patPlotBorder = ax.add_artist(Rectangle((-10, -10), 20, 20, fill=False, color='k', linewidth=2))
ax.grid(True)
fig.set_tight_layout(True)
ax.scatter(X, Y, c="b", marker="o", s=40)
plt.show()

【问题讨论】:

    标签: python python-3.x matplotlib


    【解决方案1】:

    无需更改大部分代码,您可以将clip_on 设置为False,从而显示完整的矩形。

    border = Rectangle((-10, -10), 20, 20, fill=False, color='k', linewidth=3, clip_on=False)
    ax.add_artist(border)
    

    由于网格线显示在坐标区内容上方,因此矩形边框内有一些灰线。


    或者,您可以使用两个轴。一种包含所有内容和修改后的脊椎位置等,另一种是您只需将脊椎加粗并删除所有其余部分。

    import numpy as np
    import matplotlib.pyplot as plt
    
    X = np.random.randint(low=-9, high=9, size=10)
    Y = np.random.randint(low=-9, high=9, size=10)
    
    fig, ax = plt.subplots()
    ax2 = fig.add_subplot(111)
    ax2.patch.set_visible(False)
    ax2.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False)
    for _, sp in ax2.spines.items():
        sp.set_linewidth(3)
    
    ax.axis([-10, 10, -10, 10])
    ax.spines['left'].set_position('zero')
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    plt.setp(ax.xaxis.get_majorticklabels()[0], ha='left')
    plt.setp(ax.xaxis.get_majorticklabels()[-1], ha='right')
    plt.setp(ax.yaxis.get_majorticklabels()[0], va='bottom')
    plt.setp(ax.yaxis.get_majorticklabels()[-1], va='top')
    
    ax.grid(True)
    fig.set_tight_layout(True)
    ax.scatter(X, Y, c="b", marker="o", s=40)
    plt.show()
    

    【讨论】:

    • 一如既往的出色回应。谢谢。 2个后续问题。首先,我实际上将绘图创建为嵌入到 Tkinter 窗口中的图形。鉴于这一事实,我不确定如何将第二个轴添加到同一个图/子图中。如果我指定 ax2 = fig.add_subplot(111)(ax1 已经是 subplot(111)),我会收到一条警告,并且两个轴都不显示。在这种情况下,我如何在单个子图上有 2 个轴?其次,关于如何轻松填充第一个和最后一个刻度标签位置的任何想法?我只看过 1 个例子,它不是很干净或清晰。再次感谢。
    • 您已经在第一个/最后一个刻度标签上添加了一些填充,对吧?关于子图,确保它们有不同的标签,ax1 = fig.add_subplot(111, label="blablubb1"),ax2 = fig.add_subplot(111, label="blablubb2")
    • 稍微浏览一下文档后,我注意到您可以指定一个“重复”轴或子图,其中一个已经存在,但定义中的某些内容必须是唯一的。使用不同的 label **kwarg 来执行此操作似乎是标准的,因此通过指定 ax2 = fig.add_subplot(111, label='ax2') 它可以完全按照您的答案所示工作。仍然不确定这是否是执行此操作的最佳/正确方法或如何处理刻度标签填充问题。
    • 我没有为任何刻度标签添加填充,到目前为止,我只是使用 ha='left' 等更改了理由。我看到另一个 SO 帖子,其中有人在理由之上添加了填充在绘图边缘和标签之间留出一些空白,但我现在找不到。我只记得它需要某种特殊的变换。
    【解决方案2】:

    您可以通过调用get_{x|y}gridlines() 访问各个网格线。每条网格线都是type Line2D 的一个对象,您可以更改它们的任何属性such as thickness, color, etc。

    ax.get_xgridlines()[0].set_linewidth(5)
    ax.get_xgridlines()[-1].set_linewidth(5)
    ax.get_ygridlines()[0].set_linewidth(5)
    ax.get_ygridlines()[-1].set_linewidth(5)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-25
      • 2021-06-14
      • 1970-01-01
      • 2012-03-14
      • 2016-10-09
      • 2012-12-19
      • 2019-12-18
      • 2015-10-14
      相关资源
      最近更新 更多