#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:
Самый простой способ-просто вручную выбрать и удалить значения, которые вы хотите удалить. Более сложной версией было бы вычисление оценки плотности ядра и фильтрация ниже определенного порога.
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)
Это приведет к удалению всех значений, которые находятся ниже определенного порога плотности.