使用 PyPlot 绘制平滑线

我得到了下面这个简单的绘制图表的脚本:

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

就像现在这样,这条直线从一个点到另一个点看起来不错,但在我看来可能会更好。我想要的是平滑两点之间的线。如果是在 Gnuplot,我会使用 ABc0进行绘图。

在 PyPlot 中有没有一种简单的方法可以做到这一点? 我找到了一些教程,但它们看起来都相当复杂。

332137 次浏览

从你的问题的上下文来看,我猜你指的是 曲线拟合曲线拟合曲线拟合而不是 反锯齿。PyPlot 没有任何内置的支持,但是您可以很容易地实现一些基本的曲线拟合,比如看到的 给你代码,或者如果您正在使用 GuiQwt,它有一个曲线拟合 模组。(您也可以从 SciPy中窃取代码来执行此操作)。

你可以自己用 scipy.interpolate.spline来平滑你的数据:

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

在 scipy 0.19.0中不推荐使用样条,改为使用 BSpline 类。

spline切换到 BSpline并不是简单的复制/粘贴,需要一些调整:

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

以前: screenshot 1

之后: screenshot 2

对于这个例子样条工作得很好,但是如果函数本质上不是光滑的,你想有光滑的版本,你也可以尝试:

from scipy.ndimage.filters import gaussian_filter1d


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

如果你增加 sigma,你可以得到一个更平滑的函数。

请小心使用这一个。它修改了原始值,可能不是您想要的。

有关一些示例,请参阅 scipy.interpolate文档。

下面的例子展示了它在线性和立方样条插值中的应用:

import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import interp1d


# Define x, y, and xnew to resample at.
x = np.linspace(0, 10, num=11, endpoint=True)
y = np.cos(-x**2/9.0)
xnew = np.linspace(0, 10, num=41, endpoint=True)


# Define interpolators.
f_linear = interp1d(x, y)
f_cubic = interp1d(x, y, kind='cubic')


# Plot.
plt.plot(x, y, 'o', label='data')
plt.plot(xnew, f_linear(xnew), '-', label='linear')
plt.plot(xnew, f_cubic(xnew), '--', label='cubic')
plt.legend(loc='best')
plt.show()

enter image description here

稍作修改以提高可读性。

这里有一个约会的简单解决方案:

from scipy.interpolate import make_interp_spline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime


data = {
datetime(2016, 9, 26, 0, 0): 26060, datetime(2016, 9, 27, 0, 0): 23243,
datetime(2016, 9, 28, 0, 0): 22534, datetime(2016, 9, 29, 0, 0): 22841,
datetime(2016, 9, 30, 0, 0): 22441, datetime(2016, 10, 1, 0, 0): 23248
}
#create data
date_np = np.array(list(data.keys()))
value_np = np.array(list(data.values()))
date_num = dates.date2num(date_np)
# smooth
date_num_smooth = np.linspace(date_num.min(), date_num.max(), 100)
spl = make_interp_spline(date_num, value_np, k=3)
value_np_smooth = spl(date_num_smooth)
# print
plt.plot(date_np, value_np)
plt.plot(dates.num2date(date_num_smooth), value_np_smooth)
plt.show()

example

另一种方法是根据使用的参数对函数进行轻微修改:

from statsmodels.nonparametric.smoothers_lowess import lowess


def smoothing(x, y):
lowess_frac = 0.15  # size of data (%) for estimation =~ smoothing window
lowess_it = 0
x_smooth = x
y_smooth = lowess(y, x, is_sorted=False, frac=lowess_frac, it=lowess_it, return_sorted=False)
return x_smooth, y_smooth

对于我的具体申请案例来说,这比其他答案更适合。

这是值得您的时间看看 海运绘制平滑线。

海运 进行计划函数将绘制数据和回归模型拟合。

下面说明了多项式和 更低的拟合:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt


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


df = pd.DataFrame(data = {'T': T, 'power': power})
    

sns.lmplot(x='T', y='power', data=df, ci=None, order=4, truncate=False)
sns.lmplot(x='T', y='power', data=df, ci=None, lowess=True, truncate=False)

enter image description here

order = 4多项式拟合过于适合这个玩具数据集。我没有在这里显示,但 order = 2order = 3的结果更差。

enter image description here

适合的 lowess = True是不适合这个微小的数据集,但可能会给更大的数据集更好的结果。

查看 海运回归教程海运回归教程以获得更多示例。

我发现最简单的 实施是使用张量板使用的指数移动平均值:

def smooth(scalars: List[float], weight: float) -> List[float]:  # Weight between 0 and 1
last = scalars[0]  # First value in the plot (first timestep)
smoothed = list()
for point in scalars:
smoothed_val = last * weight + (1 - weight) * point  # Calculate smoothed value
smoothed.append(smoothed_val)                        # Save it
last = smoothed_val                                  # Anchor the last smoothed value
        

return smoothed




ax.plot(x_labels, smooth(train_data, .9), x_labels, train_data)


enter image description here