我有一个带有一些异常值(错误的测量值)的图:
虽然基本数据很好。我只想删除与“当前平均值”相差太远的所有内容。我尝试使用pd.rolling().mean()
,但没有令人满意的结果:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
data = np.genfromtxt('shard_height_plot.csv', delimiter = ',')
df = pd.DataFrame(data)
df.set_index(0, inplace = True)
df2 = df.rolling(20).mean()
plt.plot(df)
plt.plot(df2)
plt.show()
我试图在网络上搜索一个好的解决方案,但找不到。删除数据点不应该那么困难,应该跳过吗?
编辑: 数据文件可在此处下载:https://ufile.io/pviuc
Edit2:
我通过改善数据集的创建解决了太多异常值的问题。
它的核心:
if abs(D - D_List[-2]) > 30:
D = D_List[-2]
D_List.pop()
D_List.append(D)
基本上,这是检查值的更改是否大于30,如果是,它将删除最后一个值,并用倒数第二个替换。不是很壮观,但正是我所需要的。我使用了答案之一,因为它太漂亮了。非常感谢你们。
答案 0 :(得分:3)
让我们尝试使用scipy.signal see docs:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import signal
data = np.genfromtxt('shard_height_plot.csv', delimiter = ',')
df = pd.DataFrame(data)
df.set_index(0, inplace = True)
df2 = df.rolling(20).mean()
b, a = signal.butter(3, 0.05)
y = signal.filtfilt(b,a, df[1].values)
df3 = pd.DataFrame(y, index=df2.index)
plt.plot(df, alpha=.3)
plt.plot(df2, alpha=.3)
plt.plot(df3)
plt.show()
输出:
使用medfilt:
y = signal.medfilt(df[1].values)
输出:
答案 1 :(得分:1)
有许多种方法可以平滑曲线(滚动平均值,GAM,平滑样条曲线等),我最喜欢的方法是Savitzky–Golay方法。
它的工作方式如下:将围绕数据点y
的小窗口回归到多项式(最小二乘)后,它使用该多项式来获取对数据点^y
的估计。然后将窗口向前移动一个数据点。
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import savgol_filter
x = np.linspace(0,5,150)
y = np.cos(x) + np.random.random(150) * 0.15
yhat = savgol_filter(y, 49, 3)
plt.plot(x,y)
plt.plot(x,yhat, color='red')
plt.show()
请注意,在周长低至20的情况下,滚动平均值不适用于您的情况,因为异常点的权重(5%)不可忽略,并且总是会引起较大的偏倚...