【问题标题】:how to handle an asymptote/discontinuity with Matplotlib如何使用 Matplotlib 处理渐近线/不连续性
【发布时间】:2010-03-29 18:27:09
【问题描述】:

在绘制具有不连续性/渐近线/奇点/其他的图形时,是否有任何自动方法可以防止 Matplotlib 在“中断”处“连接点”? (请参阅下面的代码/图片)。
我读到 Sage 有一个看起来不错的 [detect_poles] 工具,但我真的希望它可以与 Matplotlib 一起使用。

import matplotlib.pyplot as plt 
import numpy as np
from sympy import sympify, lambdify
from sympy.abc import x

fig = plt.figure(1) 
ax = fig.add_subplot(111) 

# set up axis 
ax.spines['left'].set_position('zero') 
ax.spines['right'].set_color('none') 
ax.spines['bottom'].set_position('zero') 
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom') 
ax.yaxis.set_ticks_position('left') 

# setup x and y ranges and precision
xx = np.arange(-0.5,5.5,0.01) 

# draw my curve 
myfunction=sympify(1/(x-2))
mylambdifiedfunction=lambdify(x,myfunction,'numpy')
ax.plot(xx, mylambdifiedfunction(xx),zorder=100,linewidth=3,color='red') 

#set bounds 
ax.set_xbound(-1,6)
ax.set_ybound(-4,4) 

plt.show()

【问题讨论】:

  • 感谢您提出这个问题;尽管您将其标记为python,但请注意,它通常是matplotlib 问题;我使用了来自 Julia 而不是 Python 的答案之一。问候。

标签: python numpy matplotlib equation sympy


【解决方案1】:

这可能不是您正在寻找的优雅解决方案,但如果只是想要大多数情况下的结果,您可以将绘制数据的大小值分别“剪辑”到+∞-∞。 Matplotlib 不会绘制这些。当然你要注意不要让你的分辨率太低或者你的剪辑阈值太高。

utol = 100.
ltol = -100.
yy = 1/(xx-2)
yy[yy>utol] = np.inf
yy[yy<ltol] = -np.inf

ax.plot(xx, yy, zorder=100, linewidth=3, color='red') 

【讨论】:

  • 这很好用。如果您有其他理由避免使用,也可以使用np.nan 而不是np.inf
  • 我花了一分钟才意识到 yy 必须是 np.array 的一个实例,而不仅仅是一个列表。
【解决方案2】:

通过使用masked arrays,您可以避免绘制曲线的选定区域。

去除 x=2 处的奇点:

import matplotlib.numerix.ma as M    # for older versions, prior to .98
#import numpy.ma as M                # for newer versions of matplotlib
from pylab import *

figure()

xx = np.arange(-0.5,5.5,0.01) 
vals = 1/(xx-2)        
vals = M.array(vals)
mvals = M.masked_where(xx==2, vals)

subplot(121)
plot(xx, mvals, linewidth=3, color='red') 
xlim(-1,6)
ylim(-5,5) 

这条简单的曲线可能更清楚地说明了哪些点被排除在外:

xx = np.arange(0,6,.2) 
vals = M.array(xx)
mvals = M.masked_where(vals%2==0, vals)
subplot(122)
plot(xx, mvals, color='b', linewidth=3)
plot(xx, vals, 'rx')
show()

【讨论】:

  • 为什么当我运行你的代码时,我仍然得到连接红色曲线的垂直直线?
  • 应根据您的目的修改此旧答案,截至 2022 年,you shouldn't use pylab anymore
【解决方案3】:

不,我认为没有内置方法可以告诉matplotlib 忽略这些 点。毕竟只是连接点,对函数一无所知 或者两点之间会发生什么。

但是,您可以使用 sympy 找到极点,然后将函数的连续部分拼凑在一起。这里有一些确实丑陋的代码:

from pylab import *
from sympy import solve
from sympy.abc import x
from sympy.functions.elementary.complexes import im

xmin = -0.5
xmax = 5.5
xstep = 0.01

# solve for 1/f(x)=0 -- we will have poles there
discontinuities = sort(solve(1/(1/(x-2)),x))

# pieces from xmin to last discontinuity
last_b = xmin
for b in discontinuities:
    # check that this discontinuity is inside our range, also make sure it's real
    if b<last_b or b>xmax or im(b):
      continue
    xi = np.arange(last_b, b, xstep)
    plot(xi, 1./(xi-2),'r-')
    last_b = b

# from last discontinuity to xmax
xi = np.arange(last_b, xmax, xstep)
plot(xi, 1./(xi-2),'r-')

xlim(xmin, xmax)
ylim(-4,4)
show()

【讨论】:

  • 这在适用性上非常有限:如果函数是 tan(x) 而不是 1/(x-2),则求解命令将找不到 1/tan(x) 的任何根。它只在这里有效,因为 1/(1/(x-2)) 被简化为 x-2。
【解决方案4】:

有同样的问题。 我的解决方案是将 X 分成两个不同的区间:一个在奇点之前,另一个在奇点之后。在同一图上绘制不同的曲线。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 2018-05-21
    • 1970-01-01
    • 2021-11-14
    • 2018-04-30
    • 2023-02-06
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多