在matplotlib中填充两个函数之间的空间:难看的补丁

2 投票
3 回答
1228 浏览
提问于 2025-04-18 15:23

我想在两个预定义的函数之间填充一些空间,也就是:

def stravinska_SII(log_SII_Ha, eps=0):
    strav_SII = 1.2 + eps + 0.61 / (log_SII_Ha - eps + 0.2)
    strav_SII[log_SII_Ha > eps + 0.05] = -2
    return strav_SII

def log_OIII_Hb_SII(log_SII_Ha, eps=0):
    return 1.30 + eps + 0.72 / (log_SII_Ha - eps - 0.32)

不过,在我调整了 np.linspace 以给函数设置合适的边界(因为它的值会无限增大到 y = +∞)之后,现在有一个区域还是没有被填满。我想问问大家有没有什么新方法可以用来填补这个空白区域……?

这里有一张我称之为“空白区域问题”的图片:

在这里输入图片描述

注意:我希望能定义一个函数,比如在 -0.2 到 0.06 之间的 y = 1.5 的水平线,然后用它来填充这个区域(因为 axhline 有点麻烦,因为它使用了缩放关系……)

我问题的完整图示是:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib import pyplot as plt

SII   = np.linspace(-3.0, 0.20)
SIIs  = np.linspace(-3.0,-0.38)

def log_OIII_Hb_SII(log_SII_Ha, eps=0):
    return 1.30 + eps + 0.72 / (log_SII_Ha - eps - 0.32)

def stravinska_SII(log_SII_Ha, eps=0):
    strav_SII = 1.2 + eps + 0.61 / (log_SII_Ha - eps + 0.2)
    strav_SII[log_SII_Ha > eps + 0.05] = -2
    return strav_SII

fig = plt.figure()
gs_left   = gridspec.GridSpec(1, 1)
ax = fig.add_subplot(gs_left[0,0])

ax.plot(SII, log_OIII_Hb_SII(SII), '-k')
ax.plot(SII, log_OIII_Hb_SII(SII, 0.1), '--k')
ax.plot(SII, log_OIII_Hb_SII(SII, -0.1), '--k')
ax.plot(SIIs, stravinska_SII(SIIs), '-.k')
ax.set_xlim(-2.0, 1.0)
ax.set_ylim(-1.5, 2.5)

ax.fill_between(SII, log_OIII_Hb_SII(SII), stravinska_SII(SII),      where=log_OIII_Hb_SII(SII)>=stravinska_SII(SII),
             facecolor='gray', alpha=0.45, edgecolor='none')

plt.show()

3 个回答

0

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,尤其是当我们不太了解这些工具的工作原理时。

比如说,当你在写代码的时候,可能会发现某个功能没有按照预期工作。这时候,你可以去一些技术论坛,比如StackOverflow,去寻找答案。在这些地方,很多人会分享他们的经验和解决方案。

有时候,问题的解决方案可能涉及到一些代码示例,这些示例可以帮助你更好地理解如何修复问题。记住,遇到问题是学习的一部分,不要气馁,慢慢来,总会找到解决办法的。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib import pyplot as plt

SII   = np.linspace(-3.0, 0.20)
SIIs  = np.linspace(-3.0,-0.38)
Y2    = np.linspace(-0.2575, 0.06)

def log_OIII_Hb_SII(log_SII_Ha, eps=0):
    return 1.30 + eps + 0.72 / (log_SII_Ha - eps - 0.32)

def stravinska_SII(log_SII_Ha, eps=0):
    strav_SII = 1.2 + eps + 0.61 / (log_SII_Ha - eps + 0.2)
    strav_SII[log_SII_Ha > eps + 0.05] = -2
    return strav_SII

def y(x):
    y = (x**2) - 1.682687002
    return y

fig = plt.figure()
gs_left = gridspec.GridSpec(1, 1)
ax = fig.add_subplot(gs_left[0,0])

ax.plot(SII, log_OIII_Hb_SII(SII), '-k')
ax.plot(SII, log_OIII_Hb_SII(SII, 0.1), '--k')
ax.plot(SII, log_OIII_Hb_SII(SII, -0.1), '--k')
ax.plot(SIIs, stravinska_SII(SIIs), '-.k')
ax.plot(Y2, y(Y2), ':k')
ax.set_xlim(-2.0, 1.0)
ax.set_ylim(-1.5, 2.5)

ax.fill_between(SII, log_OIII_Hb_SII(SII), stravinska_SII(SII),    where=log_OIII_Hb_SII(SII)>=stravinska_SII(SII),
             facecolor='gray', alpha=0.45, edgecolor='none')

ax.fill_between(Y2, y(Y2), log_OIII_Hb_SII(Y2),
             facecolor='gray', alpha=0.45, edgecolor='none')

plt.show()
0

stravinska_SII 在 x=-0.2 这个位置有一个渐近线。Matplotlib(一个绘图工具)正在尝试在 x 大于 -0.2 的地方填充线的上方。你正在使用 fill_betweenwhere= 参数来隐藏这个填充。

你需要要么修改你的函数 stravinska_SII,让它在 x=-0.2 以上不产生很大的正数,要么接受在这条线的上方填充是合适的这个事实。

3

fill_between这个功能在处理连续的数据时效果很好,特别是当X轴的数据表现得很好的时候。如果数据不太好,那你可能需要考虑其他的方法。

一种方法是手动创建一个多边形。这个多边形会有以下的边:

  • 第一个限制曲线上的点
  • 第二个限制曲线上的点

这个方法的好处是你不需要考虑X和Y的限制,甚至可以使用参数曲线,如果你愿意的话。

应用到你的简单例子中:

# create the limiting polygon
vert_x = np.concatenate((SII, SIIs[::-1]))
vert_y = np.concatenate((log_OIII_Hb_SII(SII), stravinska_SII(SIIs[::-1]))) 

p = plt.Polygon(np.column_stack((vert_x, vert_y)), facecolor='gray', alpha=.45, edgecolor='none')

ax.add_artist(p)

这样你的例子就变成了:

enter image description here

撰写回答