2015-01-28 2 views
1

Если я собираю некоторые экспериментальные данные и загружаю их в Python, что является наиболее эффективным методом удаления «стационарных» данных? Ниже приведен графический пример того, что у меня есть. Я хочу удалить элементы массива z, где градиент почти равен 0 (т. Е. Около первых 60 элементов).Python, удаляющий «стационарные» данные из массива

Тогда у меня остался бы шумный кривый синуса для последующего анализа.

import numpy as np 
import matplotlib.pyplot as plt 

x = np.linspace(0,5,60) 

z = np.zeros(120) 
z[0:60] = 1e-2*x + 10 
z[60:120] = np.sin(x) + 0.1*np.random.randn(len(x)) + 10 

# plt.figure() 
# plt.plot(z) 
# plt.show() 

Edit: Пробовал решение Парадизо: z = z[ np.gradient(z) > 1E-1 ]

Аналогичные результаты для установки > 1e-2, > 1e-5 и т.д.

Исходные данные:

before

После implementin г раствор:

after

ответ

2

Одним из вариантов является использование NumPy для вычисления градиента явно (он использует только центральную разностную схему), а затем использовать булеву функцию индексирования Numpy (иначе индексные массивы), чтобы отфильтровать индексы с небольшими значения производной:

import numpy as np 

z = np.zeros(120) 
z[0:60] = 1e-2*x + 10 
z[60:120] = np.sin(x) + 0.1*np.random.randn(len(x)) + 10 

z = z[ np.gradient(z) > 1E-1 ] 

EDIT:

Я немного смущен неудачей продемонстрированной выше - я был не в состоянии воспроизвести его. Тем не менее, вы могли бы сделать фильтр немного более надежным, добавив ограничение, что вы только отфильтровать данные вблизи среднего значения:

import numpy as np 
import matplotlib.pyplot as plt 

x = np.linspace(0,5,60) 

z = np.zeros(120) 
z[0:60] = 1e-2*x + 10 
z[60:120] = np.sin(x) + 0.1*np.random.randn(len(x)) + 10 

# Take some markers of the data - first and second derivatives should  be plenty to filter out flat signals 
z0 = np.mean(z) 
dz = np.gradient(z) 
ddz = np.gradient(dz) 

plt.figure(figsize=(6, 2)) 
plt.subplot(1, 3, 1) 

# Plot the original signal 
plt.plot(z) 
plt.xticks([ 30*i for i in range(5) ]) 

thresh = 1E-3 
# First try filtering on the 1st derivative 
bool_result = np.abs(dz) > thresh 

plt.subplot(1, 3, 2) 
plt.plot(z0+bool_result) 
plt.plot(z[bool_result]) 
plt.yticks([]); plt.xticks([ 30*i for i in range(5) ]) 

# Now try filtering on both the first and proximity to the mean 
bool_result = np.logical_not(np.logical_and(np.abs(dz) < thresh, np.abs(z-np.mean(z)) < .2)) 

plt.subplot(1, 3, 3) 
plt.plot(z0+bool_result) 
plt.plot(z[bool_result]) 
plt.yticks([]); plt.xticks([ 30*i for i in range(5) ]) 
plt.savefig("FilterResults.png") 

Ниже приведены результаты фильтрации (синие кривые показывают фильтр в двух последних изображений) : Filter results

+0

У меня есть несколько партий данных. Могут ли «малые значения производной» быть малыми по отношению к кривой sin? например если бы у меня было '0.01 * np.sin (x)', а также '27 * np.sin (x)' для разных партий, а часть '1e-2 * x + 10' осталась прибл. то же самое, как с этим бороться? –

Смежные вопросы