У меня есть два набора данных из разных пульсоксиметров, и выстройте их с помощью pyplot, как показано ниже. Как вы можете видеть, зеленый лист данных имеет много выбросов (вертикальные капли). В своей работе я определил эти затраты как недействительные для моего статистического анализа, они, безусловно, не должны быть измерениями. Поэтому я утверждаю, что могу просто удалить их.
Характеристики этих значений изгоев - это одиночные (или верхние два) значения outliers (см. Ниже df). "Реальные" значения образца либо совпадают с предыдущим значением, либо +-1. Например, в java (псевдокод) я бы сделал что-то вроде:
for(i; i <df.length; i++)
if (df[i+1|-1].spo2 - df[i].spo2 > 1|-1)
df[i].drop
Какими будут pandas (numpy?), Эквивалентные тому, что я пытаюсь сделать, удалить значения, которые больше/меньше 1 по сравнению с последним/следующим значением?
ДФ:
time, spo2
1900-01-01 18:18:41.194 98.0
1900-01-01 18:18:41.376 98.0
1900-01-01 18:18:41.559 78.0
1900-01-01 18:18:41.741 98.0
1900-01-01 18:18:41.923 98.0
1900-01-01 18:18:42.105 90.0
1900-01-01 18:18:42.288 97.0
1900-01-01 18:18:42.470 97.0
1900-01-01 18:18:42.652 98.0
посмотрите на pandas.DataFrame.shift. Это операция по столбцам, которая сдвигает все строки в данном столбце в другую строку другого столбца:
# original df
x1
0 0
1 1
2 2
3 3
4 4
# shift down
df.x2 = df.x1.shift(1)
x1 x2
0 0 NaN # Beware
1 1 0
2 2 1
3 3 2
4 4 3
# Shift up
df.x2 = df.x1.shift(-1)
x1 x2
0 0 1
1 1 2
2 2 3
3 3 4
4 4 NaN # Beware
Вы можете использовать это для перемещения spo2
временной метки n+1
рядом с spo2
в строке timestamp n
. Затем фильтруйте на основе условий, применяемых к этой строке.
df['spo2_Next'] = df['spo2'].shift(-1)
# replace NaN to allow float comparison
df.spo2_Next.fillna(1, inplace = True)
# Apply your row-wise condition to create filter column
df.loc[((df.spo2_Next - df.spo2) > 1) or ((df.spo2_Next - df.spo2) < 1), 'Outlier'] = True
# filter
df_clean = df[df.Outlier != True]
# remove filter column
del df_clean['Outlier']
Когда вы фильтруете рамку данных pandas, например:
df [df.colum1 = 2 & df.colum2 <3], вы:
Поэтому вам просто нужно создать итеративный алгоритм над фреймом данных для создания такого логического массива и использовать его для фильтрации фрейма данных, как в:
import pandas as pd
data = [['Alex',10],['Bob',12],['Clarke',13]]
df = pd.DataFrame(data,columns=['Name','Age'])
df[ [True, False, True]]
Вы также можете создать закрытие для фильтрации кадра данных (используя df.apply) и сохранить предыдущие наблюдения в закрытии для обнаружения резких изменений, но это было бы слишком сложно. Я бы выбрал прямое императивное решение.