Не удаляются выбросы в таблице pandas

Рейтинг: 0Ответов: 2Опубликовано: 04.05.2023

Пытаюсь удалить выбросы в таблице. Данные можно скачать по этой ссылке: http://data.insideairbnb.com/belize/bz/belize/2023-03-30/visualisations/listings.csv
Загружаю таблицу:

df = pd.read_csv('listings.csv')
df.head(5)

Строю диаграмму "Ящик с усами", чтобы проверить на выбросы.

all_numeric = ['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month',
               'calculated_host_listings_count','availability_365', 'number_of_reviews_ltm']

for col in all_numeric:
    plt.figure(figsize=(10, 5)) # Создаем frame
    sns.boxplot(x=df[col]) # boxplot это ящик с усами. в скобочках указывается столбец.
    plt.show()

Потом я удаляю выбросы таким способом:

for col in all_numeric:
    Q1 = df[col].quantile(0.25)
    Q3 = df[col].quantile(0.75)
    IQR = Q3 - Q1

    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR

    df = df[(df[col] >= lower_bound) & (df[col] <= upper_bound)]

После удаления выбросов я еще раз строю диаграмму "Ящик с усами", но на ней отображаются выбросы. Подскажите, пожалуйста, так и должно быть или я что-то делаю не так?

Ответы

▲ 1

Повторю здесь комментарий под вопросом:

Когда Вы последовательно применяете фильтрацию к каждой из колонок, то на каждой последующей итерации, следующая колонка представляет собой уже не тот набор данных, который был изначально, так как Вы уже отрезали часть данных по данным из предыдущих колонок. В результате, Вы рушите данные и когда Вы строите боксплот после фильтрации, эти ящики уже совсем не те, что были в начале, а совсем другое распределение. Я бы не удалял строки при фильтрации, а сделал бы обратную фильтрацию и забивал бы значения, выпадающие за усы, NaN. Тогда изначальный DF и распределения останутся целы.

Попробуйте вот так (меняем последнюю строку в цикле фильтрации):

df[col].where((df[col] >= lower_bound) & (df[col] <= upper_bound), other = np.nan, inplace=True)

Если не подключаете numpy, то np.nan поменяйте на float('nan')

▲ 0

попробуйте указать параметр showfliers = False:

sns.boxplot(x=df[col], showfliers = False)

причем, ненужно удалять выбросы вручную:

f = pd.read_csv("listings.csv")
#df.head()

all_numeric = ['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month',
               'calculated_host_listings_count','availability_365', 'number_of_reviews_ltm']

plt.figure(figsize=(10, 5))
sns.boxplot(x=df["price"])

введите сюда описание изображения

sns.boxplot(x=df["price"], showfliers=False)

введите сюда описание изображения

Странно, что этот параметр не упоминается в официальной документации к boxplot, но присутствует в официальной документации к boxenplot.

Кроме того, с помощью инструментария matplotlib можно получить сами выбросы и избавиться от них в датафрейме. Напрмер:

from matplotlib.cbook import boxplot_stats
outliers = boxplot_stats(df["price"]).pop(0)['fliers']
res = df[~df["price"].isin(outliers)]