2010-03-29 30 views
21

Khi vẽ đồ thị với một gián đoạn/asymptote/singularity/bất cứ điều gì, là có bất kỳ cách tự động để ngăn chặn Matplotlib từ 'tham gia các dấu chấm' trên 'break'? (vui lòng xem mã/hình ảnh bên dưới).
Tôi đọc rằng Sage có một cơ sở [detect_poles] trông đẹp, nhưng tôi thực sự muốn nó hoạt động với Matplotlib.làm thế nào để xử lý một asymptote/gián đoạn với 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() 

Discontinuity

+1

Cảm ơn bạn đã này câu hỏi; mặc dù bạn đã gắn thẻ nó là 'python', hãy lưu ý rằng nó thường là câu hỏi' matplotlib'; Tôi đã sử dụng bản thân mình một trong những câu trả lời từ Julia chứ không phải là Python. Trân trọng. –

Trả lời

11

Điều này có thể không phải là giải pháp thanh lịch bạn đang tìm kiếm, nhưng nếu chỉ muốn kết quả cho hầu hết các trường hợp, bạn có thể "clip" lớn và các giá trị nhỏ của dữ liệu được vẽ của bạn theo số lần lượt là +∞-∞. Matplotlib không âm mưu này. Tất nhiên bạn phải cẩn thận không làm cho độ phân giải của bạn quá thấp hoặc ngưỡng cắt của bạn quá cao.

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') 
+0

Điều này hoạt động rất tốt. Bạn cũng có thể sử dụng 'np.nan' thay cho' np.inf' nếu bạn có lý do khác để tránh '∞' – MackM

5

Không, tôi nghĩ không có cách nào tích hợp để nói matplotlib để bỏ qua những điểm. Sau khi tất cả, nó chỉ kết nối điểm và không biết gì về chức năng hoặc những gì xảy ra ở giữa các điểm.

Tuy nhiên, bạn có thể sử dụng sympy để tìm các cực và sau đó vá các phần liên tục của hàm của bạn lại với nhau. Dưới đây một số mã phải thừa nhận là xấu xí mà không chính xác rằng:

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() 

example http://i43.tinypic.com/30mvbzb.jpg

+0

Điều này rất hạn chế trong khả năng áp dụng: nếu hàm là tan (x) thay vì 1/(x-2), lệnh giải quyết sẽ không tìm thấy bất kỳ gốc nào của 1/tan (x). Nó chỉ hoạt động ở đây vì 1/(1/(x-2)) được đơn giản hóa thành x-2. –

20

Bằng cách sử dụng masked arrays bạn có thể tránh vẽ các vùng được chọn của đường cong.

Để loại bỏ các điểm kỳ dị tại 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) 

đường cong đơn giản này có thể là một chút rõ ràng hơn mà điểm bị loại trừ:

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() 

enter image description here

+0

tại sao khi tôi chạy mã của bạn, tôi vẫn nhận được đường thẳng thẳng nối các đường cong màu đỏ? –