Как удалить выбросы из диаграммы рассеяния XY

#python #matplotlib #cluster-computing #outliers

Вопрос:

Я работаю над проектом, в котором есть значения X и Y, и я пытаюсь исследовать область, в которой не должно быть данных. Как видно из рисунков, большая часть данных собрана по сторонам красной линии, и некоторые данные находятся внутри красной линии. Я просто хочу удалить эти выбросы, но не смог этого добиться. Я пытаюсь использовать обратные алгоритмы KNN или вычисления расстояний, но они не работали в моих данных, или я не смог этого сделать. Есть ли какое — либо возможное решение для этого?

Мой код на python для точечной диаграммы приведен ниже.

 import pyodbc import matplotlib.pyplot as plt from astroML.plotting import scatter_contour import numpy as np import pandas as pd  conn = pyodbc.connect('Driver={SQL Server};'  'Server=test;'  'Database=test;'  'Trusted_Connection=yes;')  sqlquery= "SELECT test FROM test"  SQL_Query = pd.read_sql_query (sqlquery, conn)   df = pd.DataFrame(SQL_Query, columns=['Data1', 'Data2'])    x = df['Data1'] y = df['Data2'] fig,ax = plt.subplots(1,1,figsize=(15,15)) scatter_contour(x,y, threshold=20, log_counts=True, ax=ax,  histogram2d_args=dict(bins=45),  plot_args=dict(marker='.', linestyle='none', color='black',  markersize=1),  contour_args=dict(cmap='summer',),  filled_contour=False)  

Рисунок 1

Рисунок 2

Ответ №1:

Самый простой способ-просто вручную выбрать и удалить значения, которые вы хотите удалить. Более сложной версией было бы вычисление оценки плотности ядра и фильтрация ниже определенного порога.

 from scipy import stats  ....  xmin = x.min()  xmax = x.max()  ymin = y.min()  ymax = y.max()  #Perform a kernel density estimate on the data:  X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]  positions = np.vstack([X.ravel(), Y.ravel()])  values = np.vstack([x, y])  kernel = stats.gaussian_kde(values)  Z = np.reshape(kernel(positions).T, X.shape)  

Это позволит вам получить 2d-аппроксимацию ваших данных размером 100х100. Если вам нужна более подробная оценка плотности ядра, вы можете изменить это значение 100 на более высокое. Если вы масштабируете свои x данные от 0 до 100, то Z значения ниже выбранного порогового значения являются точками, которые вы хотите удалить.

 df['x_to_scale'] = (100*(x - np.min(x))/np.ptp(x)).astype(int)  df['y_to_scale'] = (100*(y - np.min(y))/np.ptp(y)).astype(int)   to_delete = zip(*np.where((Zlt;your_threshold) == True))  df.drop(df.apply(lambda x: (x['x_to_scale'], x['y_to_scale']), axis=1)  .isin(to_delete)  .loc[lambda x: x == True]  .index)  

Это приведет к удалению всех значений, которые находятся ниже определенного порога плотности.