Я действительно думаю, что z-счёт с использованием scipy.stats.zscore () - это то, что нужно. Посмотрите на связанную проблему в этой записи . Там они сосредотачиваются на том, какой метод использовать до удаления потенциальных выбросов. На мой взгляд, ваша задача немного проще, поскольку, судя по предоставленным данным, было бы довольно просто определить потенциальные выбросы без необходимости преобразования данных. Ниже приведен фрагмент кода, который делает именно это. Просто помните, что то, что выглядит и не похоже на выбросы, будет полностью зависеть от вашего набора данных. И после удаления некоторых выбросов, которые раньше не выглядели как выбросы, вдруг сделают это сейчас. Посмотрите:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy import stats
# your data (as a list)
data = [0.5,0.5,0.7,0.6,0.5,0.7,0.5,0.4,0.6,4,0.5,0.5,4,5,6,0.4,0.7,0.8,0.9]
# initial plot
df1 = pd.DataFrame(data = data)
df1.columns = ['data']
df1.plot(style = 'o')
# Function to identify and remove outliers
def outliers(df, level):
# 1. temporary dataframe
df = df1.copy(deep = True)
# 2. Select a level for a Z-score to identify and remove outliers
df_Z = df[(np.abs(stats.zscore(df)) < level).all(axis=1)]
ix_keep = df_Z.index
# 3. Subset the raw dataframe with the indexes you'd like to keep
df_keep = df.loc[ix_keep]
return(df_keep)
Исходные данные:
Тестовый прогон 1: Z-счет = 4:
Как видите, данные не были удалены, поскольку уровень был установлен слишком высоко.
Тестовый прогон 2: Z-оценка = 2:
Теперь мы куда-то добираемся. Два выброса были удалены, но все еще остаются некоторые сомнительные данные.
Тестовый прогон 3: Z-оценка = 1,2:
Это выглядит действительно хорошо. Остальные данные теперь распределяются более равномерно, чем раньше. Но теперь точка данных, выделенная исходной точкой данных, начинает выглядеть как потенциальный выброс. Итак, где остановиться? Это будет зависеть от вас!
РЕДАКТИРОВАТЬ: Вот и все для легкого копирования и вставки:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy import stats
# your data (as a list)
data = [0.5,0.5,0.7,0.6,0.5,0.7,0.5,0.4,0.6,4,0.5,0.5,4,5,6,0.4,0.7,0.8,0.9]
# initial plot
df1 = pd.DataFrame(data = data)
df1.columns = ['data']
df1.plot(style = 'o')
# Function to identify and remove outliers
def outliers(df, level):
# 1. temporary dataframe
df = df1.copy(deep = True)
# 2. Select a level for a Z-score to identify and remove outliers
df_Z = df[(np.abs(stats.zscore(df)) < level).all(axis=1)]
ix_keep = df_Z.index
# 3. Subset the raw dataframe with the indexes you'd like to keep
df_keep = df.loc[ix_keep]
return(df_keep)
# remove outliers
level = 1.2
print("df_clean = outliers(df = df1, level = " + str(level)+')')
df_clean = outliers(df = df1, level = level)
# final plot
df_clean.plot(style = 'o')