Вывести часть датафрейма, соответствующую экстремальным значениям
У меня есть график ящик с усами, который показывает по годам уровень счастья в мире. И за три последних года я увидела, что есть экстремальные значения.
Задача: вывести фрагмент DataFrame который соответствует этим экстремальным значениям.
Я использовала такой код:
df_all_years[(df_all_years['Ladder score'] < 3.2)&(df_all_years['year']>2018)]
НО он выводит больше информации, чем хотелось бы получить.
Идея у меня состоит в том, что бы указать значения за пределами интерквартального размаха: q1-iqr*1.5.
А как это сделать я не понимаю.
Использовала цикл for и if, но ничего не получается.
(
)
График ящик с усами по парметру "Ladder Score" - уровень счастья'
Ответы (1 шт):
Не хотел использовать построчный .apply, так как ничего, кроме синтаксиса он не улучшает по сравнению с for, но так ничего и не придумал.
Решение
C помощью .groupby, считаем края нижних усов для каждого года. (Комментарий: фильтрацию по годам можно добавить на любом этапе).
С помощью построчного .apply создаем маску с использованием данных из предыдущего этапа и применяем ее к исходному датафрейму.
import random
import pandas as pd
# создадим тестовый датафрейм с нормальным распределением в колонке 'Ladder score'
dic = {
'year': [random.randint(2017,2020) for _ in range(1000)],
'Ladder score': [int(random.normalvariate(500, 90)) for _ in range(1000)],
'some': [random.randint(100, 999) for _ in range(1000)]
}
df = pd.DataFrame.from_dict(dic)
# в переменную gr получим подсчитанные нижние усы для каждого года
gr = df.groupby('year')['Ladder score'].apply(
lambda x: x.quantile(0.25) - (x.quantile(0.75) - x.quantile(0.25)) * 1.5
)
# создадим маску
mask = df.apply(lambda x: x['Ladder score'] < gr[x['year']], axis=1)
print(df[mask])
Повторю, этот код вернет все аномалии по всем годам. Чтобы ограничить нужными годами, можете применить фильтр на любом этапе.
print(df[mask & (df['year'] > 2018)])