Заменить выбросы соседним значением - PullRequest
0 голосов
/ 09 октября 2018

У меня есть график с некоторыми выбросами (неправильные измерения):

enter image description here

Хотя базовые данные хороши.Я хочу просто удалить все, что слишком далеко от «текущего среднего».Я пытался использовать 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()

enter image description here

Я пытался найти в Интернете хорошее решение, но не смогнайти один.Не должно быть так сложно удалить точки данных, которые прыгают через крышу, не так ли?

Редактировать: файл данных можно загрузить здесь: https://ufile.io/pviuc

Редактировать2:

Я решил эту проблему со слишком многими выбросами, улучшив создание моего набора данных.

Суть его:

if abs(D - D_List[-2]) > 30:
            D = D_List[-2]
            D_List.pop()
            D_List.append(D)

По сути, это проверяет, больше ли изменение значения, чем 30, и удаляет ли последнее значение и заменяет его вторым последним.Не очень эффектно, но именно то, что мне нужно.Я использовал один из ответов, потому что он намного красивее.Большое спасибо, ребята.

enter image description here

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Существует множество способов сглаживания кривой (скользящее среднее, 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()

enter image description here

Обратите внимание, что скользящее среднее не может работать в вашем случае с периметром, так какниже 20, поскольку точка выброса будет иметь незначительный вес (5%) и всегда будет вызывать большой уклон ...

0 голосов
/ 09 октября 2018

Давайте попробуем использовать scipy.signal, см. Документы :

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

Вывод:

enter image description here

Используйте medfilt:

y = signal.medfilt(df[1].values)

Вывод:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...