Matplotlib自动缩放行为与多个绘图的预期不同

2024-09-28 22:39:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要绘制线条和阴影区域。着色区域延伸到绘图边缘之外,我希望保持绘图限制与绘制着色区域之前相同。我还需要任何自动缩放更改来考虑当前轴,以便限制永远不会缩小,并允许将来绘制的任何线调整轴,因为如果我没有指定xlim,它们通常会调整轴。 下面的代码生成一个图像,显示我得到了什么以及我期望得到什么。我试过auto=True、False、None,但它们没有达到我对分层图的期望

我真的很感激你能帮我做这件事,因为我已经做了好几个小时了

import matplotlib.pyplot as plt
import numpy as np

def shade(X, power1, power2, offset, color):
    '''
    This function plots a shaded region that is larger than the lines
    It should not adjust the axes limits as I do not want to display anything larger than the lines
    It needs to take into account previous axes limits so the axes limits never shrink
    It needs to leave the axes autoscaling in a way that will allow future line plots (done by plotter) to adjust the axes limits so nothing is cut off
    '''
    xlims = plt.xlim() #get the xlims to be reimposed after the shaded region is plotted
    xmin = min(X)
    xmax = max(X)
    X_enlarged = np.linspace(xmin, xmax * 2, 100)
    plt.fill_between(X_enlarged, X_enlarged ** power1 + offset, X_enlarged ** power2 + offset, alpha=0.2, color=color)
    #reimpose the xlims    
    plt.xlim(xlims, auto=None)  # this line is the key to how the xlims are adjusted

def plotter(xmax, offset, color):
    power1 = 2
    power2 = 2.5
    X1 = np.linspace(0, xmax, 100)
    Y1 = X1 ** power1
    Y2 = X1 ** power2
    plt.plot(X1, Y1 + offset, color=color)
    plt.plot(X1, Y2 + offset, color=color)
    shade(X1, power1, power2, offset, color=color)


plt.subplot(231)
plotter(xmax=10, offset=0, color='red')
plt.subplot(232)
plotter(xmax=15, offset=1000, color='blue')
plt.subplot(233)
plotter(xmax=12, offset=2000, color='green')
plt.subplot(234)
plotter(xmax=10, offset=0, color='red')
plotter(xmax=15, offset=1000, color='blue')
plotter(xmax=12, offset=2000, color='green')
plt.title('What I get\nwhen combined')
plt.subplot(236)
plotter(xmax=10, offset=0, color='red')
plotter(xmax=15, offset=1000, color='blue')
plotter(xmax=12, offset=2000, color='green')
plt.xlim(-1, 16)
plt.title('What I want\nwhen combined')
plt.tight_layout()
plt.show()

code_output


Tags: thetoispltoffsetcolorx1plotter
1条回答
网友
1楼 · 发布于 2024-09-28 22:39:33

所以我设法解决了自己的问题。 这个matplotlibexample非常有用

下面是我的完整解决方案。我将提供我所学到的,希望有一天这能帮助别人

为什么我的第一个代码没有按预期工作?

在matplotlib中绘制某些内容时,大多数人绘制内容的方式是在许多其他函数之间或其中一个函数之间使用plt.plot或plt.fill_。这些函数只是使matplotlib易于使用的API,它们自动化了后台的大量工作,包括将直线或多边形添加到直线集合或多边形集合的过程。matplotlib使用了很多collections。不幸的是,当您以这种方式打印某个对象时,当该对象自动添加到集合中时,您无法完全控制该对象的属性。在自动缩放方面,我们可以控制的是所有对象的全局自动缩放规则。因此,使用类似plt.xlim(auto=False)的方法将设置自动缩放,以便在后续绘图添加到绘图时不更新。类似地,使用auto=True(默认值)将更新自动缩放,auto=None使其保持不变。像scalex和scaley这样的Kwarg似乎做了类似的事情,并且在全球范围内工作。我需要的是,在计算缩放限制时,将着色区域(多边形)从列表中删除,但全局自动缩放规则保持不变,以便在以后打印任何内容时,缩放将调整以包含它。没有一个自动缩放关键字为我添加到绘图中的每个对象提供了这种级别的控制

下面的解决方案是如何工作的?

变量“polygon”是按照PolyCollection希望接收多边形的方式创建的。它实际上是沿多边形底部从左到右,然后沿顶部从右到左的坐标列表。通过使用add_集合,我能够使用kwarg autolim=False。这将更改多边形添加到多边形集合的方式,并确保在自动缩放查看打印上的所有对象时,将其从对象列表中删除。 重要的是,整个绘图的自动缩放属性不会更改,因此,当我添加其他内容(如正弦波线)时,自动缩放会重新计算限制

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import PolyCollection


def shade(X, power1, power2, offset, color):
    x = np.linspace(min(X), max(X) * 2, 100)
    y1 = x ** power1 + offset
    y2 = x ** power2 + offset
    polygon = np.column_stack([np.hstack([x, x[::-1]]), np.hstack([y1, y2[::-1]])])  # this is equivalent to fill as it makes a polygon
    col = PolyCollection([polygon], color=color, alpha=0.2)
    plt.gca().add_collection(col, autolim=False)


def plotter(xmax, offset, color):
    power1 = 2
    power2 = 2.5
    X1 = np.linspace(0, xmax, 100)
    Y1 = X1 ** power1
    Y2 = X1 ** power2
    plt.plot(X1, Y1 + offset, color=color)
    plt.plot(X1, Y2 + offset, color=color)
    shade(X1, power1, power2, offset, color=color)


final_lineX = np.linspace(0, 22, 100)
final_lineY = np.sin(final_lineX) * 500

plt.subplot(231)
plotter(xmax=10, offset=0, color='red')
plt.subplot(232)
plotter(xmax=15, offset=1000, color='blue')
plt.subplot(233)
plotter(xmax=12, offset=2000, color='green')
plt.subplot(223)
plotter(xmax=10, offset=0, color='red')
plotter(xmax=15, offset=1000, color='blue')
plotter(xmax=12, offset=2000, color='green')
plt.title('combined')
plt.subplot(224)
plotter(xmax=10, offset=0, color='red')
plotter(xmax=15, offset=1000, color='blue')
plotter(xmax=12, offset=2000, color='green')
plt.plot(final_lineX, final_lineY)
plt.title('combined\nwith extra line')
plt.subplots_adjust(left=0.11, bottom=0.07, right=0.95, top=0.95, wspace=0.41, hspace=0.44)
plt.show()

solution_output

相关问题 更多 >