使用PyPlot绘制平滑线

Pau*_*aul 104 python plot matplotlib curvesmoothing

我有以下简单的脚本绘制图表:

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()
Run Code Online (Sandbox Code Playgroud)

就像现在一样,这条直线从一点到另一点直线看起来不错,但在我看来可能更好.我想要的是平滑点之间的界限.在Gnuplot,我会用smooth cplines.

在PyPlot中有一种简单的方法吗?我找到了一些教程,但它们看起来都相当复杂.

Oli*_*ier 150

您可以使用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()
Run Code Online (Sandbox Code Playgroud)

spline在scipy 0.19.0中已弃用,请改用Bspline类.

切换splineBSpline不是简单的复制/粘贴,需要稍微调整:

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()
Run Code Online (Sandbox Code Playgroud)

之前: 截图1

后: 截图2

  • 如果 T 未排序,这将不起作用。并且如果functiton(T) 不是一对一的。 (4认同)
  • 哈哈,这并不困难.干杯! :)只是为其他可能正在寻找的注释:我必须导入scipy才能使用linspace(). (2认同)
  • 300是T.min()和T.max()之间的分数.我使用1000,它看起来一样.试试5虽然你会看到一个区别. (2认同)
  • `spline`已被弃用!spline在scipy 0.19.0中已弃用,请改用BSpline类:`from scipy.interpolate import BSpline` (2认同)
  • 什么是“k = 3”? (2认同)
  • @AminGuermazi `k=3` 是样条插值的程度:[https://docs.scipy.org/doc/scipy/reference/ generated/scipy.interpolate.make_interp_spline.html](https:// docs.scipy.org/doc/scipy/reference/ generated/scipy.interpolate.make_interp_spline.html)。因此,如果您使用更大的数字,例如“k=6”,曲线应该更平滑。 (2认同)

Tom*_*eck 19

我发现的最简单的实现之一是使用 Tensorboard 使用的指数移动平均线:

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), label="Train Smooth")  # label="Train") # uncomment to reproduce figure below
ax.plot(x_labels, train_data, label="Train")  # label="Train Smooth") # uncomment to reproduce figure below

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这是一个很好的建议,尽管我相信曲线的标签在图例中被交换了。 (2认同)

Saj*_*uzi 11

对于此示例,样条曲线效果很好,但是如果函数固有地不平滑,并且您想要平滑的版本,则还可以尝试:

from scipy.ndimage.filters import gaussian_filter1d

ysmoothed = gaussian_filter1d(y, sigma=2)
plt.plot(x, ysmoothed)
plt.show()
Run Code Online (Sandbox Code Playgroud)

如果增加sigma,则可以获得更平滑的功能。

谨慎行事。它会修改原始值,可能不是您想要的。

  • 谨慎行事。它会修改原始值,可能不是您想要的。 (6认同)

Nic*_*tin 7

我认为你的意思是曲线拟合而不是你的问题背景下的抗锯齿.PyPlot没有任何内置的这种支持,但你可以很容易地实现一些基本的曲线拟合自己,喜欢看到的代码在这里,或者如果你使用GuiQwt它有一个曲线拟合模块.(您也可以从SciPy中窃取代码来执行此操作).


Mat*_*haq 7

有关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()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

稍微修改以提高可读性。


tob*_*s88 6

这是日期的简单解决方案:

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()
Run Code Online (Sandbox Code Playgroud)

例子