Vẽ đường trơn bằng PyPlot


111

Tôi có một đoạn mã đơn giản sau đây vẽ một biểu đồ:

import matplotlib.pyplot as plt
import numpy as np

T = np.array([6, 7, 8, 9, 10, 11, 12])
power = np.array([1.53E+03, 5.92E+02, 2.04E+02, 7.24E+01, 2.72E+01, 1.10E+01, 4.70E+00])

plt.plot(T,power)
plt.show()

Như hiện tại, đường thẳng đi thẳng từ điểm này đến điểm khác có vẻ ổn, nhưng theo tôi có thể tốt hơn. Những gì tôi muốn là làm phẳng ranh giới giữa các điểm. Trong Gnuplot, tôi sẽ lập mưu với smooth cplines.

Có cách nào dễ dàng để làm điều này trong PyPlot không? Tôi đã tìm thấy một số hướng dẫn, nhưng chúng đều có vẻ khá phức tạp.

Câu trả lời:


166

Bạn có thể sử dụng scipy.interpolate.splineđể tự làm mịn dữ liệu của mình:

from scipy.interpolate import spline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300)  

power_smooth = spline(T, power, xnew)

plt.plot(xnew,power_smooth)
plt.show()

spline không được dùng nữa trong scipy 0.19.0, hãy sử dụng lớp BSpline để thay thế.

Chuyển từ splinesang BSplinekhông phải là một bản sao / dán đơn giản và yêu cầu một chút tinh chỉnh:

from scipy.interpolate import make_interp_spline, BSpline

# 300 represents number of points to make between T.min and T.max
xnew = np.linspace(T.min(), T.max(), 300) 

spl = make_interp_spline(T, power, k=3)  # type: BSpline
power_smooth = spl(xnew)

plt.plot(xnew, power_smooth)
plt.show()

Trước: ảnh chụp màn hình 1

Sau: ảnh chụp màn hình 2


2
Haha, điều đó không khó. Chúc mừng! :) Chỉ một lưu ý cho những người khác có thể đang tìm kiếm: Tôi đã phải nhập scipy để sử dụng linspace ().
Paul

Rất tiếc, xin lỗi, đáng lẽ phải sử dụng np.linspace. Đã sửa trong câu trả lời của tôi.
Olivier Verdier

2
300 là bao nhiêu điểm để tạo ra giữa T.min () và T.max (). Tôi đã sử dụng 1000 và nó trông giống nhau. Hãy thử với 5 cái và bạn sẽ thấy sự khác biệt.
CornSmith,

2
splinekhông được chấp nhận! spline bị phản đối trong scipy 0.19.0, lớp sử dụng BSpline thay vì:from scipy.interpolate import BSpline
user890739

2
Điều này sẽ không hoạt động nếu chữ T không được sắp xếp. Và cũng như nếu functiton (T) không phải là 1-1.
Rahat Zaman

28

Đối với ví dụ này, spline hoạt động tốt, nhưng nếu chức năng vốn dĩ không trơn tru và bạn muốn có phiên bản làm mịn, bạn cũng có thể thử:

from scipy.ndimage.filters import gaussian_filter1d

ysmoothed = gaussian_filter1d(y, sigma=2)
plt.plot(x, ysmoothed)
plt.show()

nếu bạn tăng sigma, bạn có thể nhận được một chức năng mượt mà hơn.

Tiến hành một cách thận trọng với điều này. Nó sửa đổi các giá trị ban đầu và có thể không phải là những gì bạn muốn.


10
Tiến hành một cách thận trọng với điều này. Nó sửa đổi các giá trị ban đầu và có thể không phải là những gì bạn muốn.
tartaruga_casco_mole

8

Tôi cho rằng ý bạn là phù hợp với đường cong và không khử răng cưa từ ngữ cảnh câu hỏi của bạn. PyPlot không có bất kỳ hỗ trợ tích hợp nào cho việc này, nhưng bạn có thể dễ dàng tự mình thực hiện một số thao tác chỉnh đường cong cơ bản, như mã được thấy ở đây hoặc nếu bạn đang sử dụng GuiQwt, nó có một mô-đun điều chỉnh đường cong . (Bạn cũng có thể ăn cắp mã từ SciPy để làm điều này).


cảm ơn. Tôi đã thử mười phương trình khác nhau và [Sử dụng các hàm cơ sở xuyên tâm để làm mịn / nội suy] [1] rbf = Rbf(x, y), fi = rbf(xi)là tốt nhất trong số đó. [1]: scipy-cookbook.readthedocs.io/items/RadialBasisFunctions.html ,
Cloud Cho

1

Xem scipy.interpolatetài liệu để biết một số ví dụ.

Ví dụ sau minh họa việc sử dụng nó cho phép nội suy tuyến tính và đường khối:

>>> from scipy.interpolate import interp1d

>>> x = np.linspace(0, 10, num=11, endpoint=True)
>>> y = np.cos(-x**2/9.0)
>>> f = interp1d(x, y)
>>> f2 = interp1d(x, y, kind='cubic')

>>> xnew = np.linspace(0, 10, num=41, endpoint=True)
>>> import matplotlib.pyplot as plt
>>> plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
>>> plt.legend(['data', 'linear', 'cubic'], loc='best')
>>> plt.show()

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.