Python Matplotlib 线图与轮廓/imshow 对齐

标签 python matplotlib

如何使用 Python 和 Matplotlib 将一个子图的视觉宽度设置为等于另一个子图的宽度?第一个图具有固定的纵横比和来自 imshow 的方形像素。然后我想在其下方放置一个线图,但我无法这样做并使所有内容对齐。

我相当确定解决方案涉及关于此 Transform Tutorial 的信息页。我试过使用 fig.transFigure、ax.transAxes、ax.transData 等,但没有成功。我需要在上面板中找到轴的宽度和高度以及偏移量,然后能够在下面板中设置轴的宽度、高度和偏移量。不应包含轴标签和刻度等或更改对齐方式。

例如下面的代码

fig = plt.figure(1)
fig.clf()

data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)

ax = fig.add_subplot(211)
ax.imshow(data, interpolation='none')
c = ax.contour(xaxis, yaxis, data, colors='k')

ax2 = fig.add_subplot(212)

enter image description here

最佳答案

matplotlib 轴的轮廓由三件事控制:

  1. 图中轴的边界框(由子图规范或特定范围控制,例如 fig.add_axes([left, bottom, width, height])。轴限制(不是计数刻度标签)将始终在此框内。
  2. adjustable 参数控制是否通过更改数据限制或轴“框”的形状来适应限制或纵横比的变化。这可以是 "datalim""box""box-forced"。 (后者用于共享轴。)
  3. 轴限制和纵横比。对于具有固定纵横比的绘图,轴框或数据限制(取决于 adjustable)将更改以保持指定的纵横比。纵横比指数据坐标,直接指坐标轴的形状。

对于最简单的情况:

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2)

data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)

axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')

axes[1].set_aspect(1)

plt.show()

enter image description here


共享轴

但是,如果您想确保它无论如何都保持相同的形状,并且您可以接受两个具有相同数据限制的图,您可以这样做:

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2), sharex=True, sharey=True)
plt.setp(axes.flat, adjustable='box-forced')

data = np.random.random((5,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,5)

axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')

axes[1].plot([-0.5, 2.5], [-0.5, 4.5])
axes[1].set_aspect(1)

plt.show()

enter image description here

但是,您可能会注意到这看起来不太正确。这是因为根据我们绘制事物的顺序,第二个子图控制着第一个子图的范围。

基本上,对于共享轴,我们最后绘制的任何内容都将控制初始范围,因此如果我们只是交换我们绘制的顺序:

    import numpy as np
    import matplotlib.pyplot as plt

    fig, axes = plt.subplots(nrows=2, sharex=True, sharey=True)
    plt.setp(axes.flat, adjustable='box-forced')

    data = np.random.random((5,3))
    xaxis = np.arange(0,3)
    yaxis = np.arange(0,5)

    axes[1].plot([-0.5, 2.5], [-0.5, 4.5])
    axes[1].set_aspect(1)

    axes[0].imshow(data, interpolation='none')
    c = axes[0].contour(xaxis, yaxis, data, colors='k')

    plt.show()

enter image description here

当然,如果您不关心所链接图的交互式缩放/平移,您可以完全跳过共享轴,而只是为了:

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2)

data = np.random.random((5,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,5)

axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')

axes[1].plot([-0.5, 2.5], [-0.5, 4.5])

# Copy extents and aspect from the first axes...
axes[1].set_aspect(axes[0].get_aspect())
axes[1].axis(axes[0].axis())

plt.show()

非共享轴

如果您不希望两个轴具有相同的数据范围,可以强制它们具有相同的大小(但如果您交互式缩放,它们将不会链接)。为此,您需要根据第二个图的范围和第一个图的范围/纵横比来计算第二个图的纵横比。

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=2)

data = np.random.random((3,3))
xaxis = np.arange(0,3)
yaxis = np.arange(0,3)

axes[0].imshow(data, interpolation='none')
c = axes[0].contour(xaxis, yaxis, data, colors='k')

axes[1].plot(np.linspace(0, 10, 100), np.random.normal(0, 1, 100).cumsum())

# Calculate the proper aspect for the second axes
aspect0 = axes[0].get_aspect()
if aspect0 == 'equal':
    aspect0 = 1.0
dy = np.abs(np.diff(axes[1].get_ylim()))
dx = np.abs(np.diff(axes[1].get_xlim()))

aspect = aspect0 / (float(dy) / dx)
axes[1].set_aspect(aspect)

plt.show()

enter image description here

关于Python Matplotlib 线图与轮廓/imshow 对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26985210/

相关文章:

python - 获取并迭代大型数据集,可以吗?为什么管理日志/appstas 不同?

python - 如何管理 "NavigationToolbar2TkAgg"工具栏的位置?

python - 什么时候需要 plt.show() 来显示情节,什么时候不需要?

python - 如何将数据值转换为matplotlib的颜色信息?

javascript - 从 javascript 调用服务器端 python 脚本

python - 按降序排列 numpy 列表的元素

python - Keras 中 Adam 优化器的衰减参数

访问数组某些部分的 Pythonic 方式

python - 如何绘制条件为 (r < 1.5*rs) 的数组?

python - 在 Pandas 中绘制二进制矩阵