Я пытаюсь отфильтровать список данных о температуре, где температура превышает порог в 7–10 градусов. Моя цель — создать отфильтрованный набор данных о днях, когда температура превышает пороговое значение, но не о промежуточных данных. Я приложил образец таблицы; в настоящее время я использую фильтры высокого/низкого уровня, которые работают, но они включают промежуточные данные, а не список дат, когда происходит выход за пределы порогового значения.
Возможно ли это с простым питоном? Заранее спасибо!
Дата | Температура | Флаг |
---|---|---|
01 января 21 | 9.20 | |
02 января 21 | 9.50 | |
03 января 21 | 10.10 | ВЕРХНИЙ |
04 января 21 | 11.00 | |
05 января 21 | 10.50 | |
06 января 21 | 10.20 | |
07 января 21 | 9,80 | |
08 января 21 | 8.50 | |
09 января 21 | 6.20 | НИЖЕ |
10 января 21 | 9,90 | |
11 января 21 | 10.10 | ВЕРХНИЙ |
12 января 21 | 10.21 | |
13 января 21 | 11.00 | |
14 января 21 | 12.10 | |
15 января 21 | 11.34 | |
16 января 21 | 9.43 | |
17 января 21 | 10.22 | ВЕРХНИЙ |
18 января 21 | 11.00 |
Чтобы получить строки, в которых столбец находится между двумя значениями (оба включительно), вы можете использовать between
. В целях демонстрации сохраните это во временном столбце
df['in_range'] = df.Temperature.between(7, 10)
чтобы получить это (пока игнорируя столбец Flag
):
>>> df.head(10)
Date Temperature in_range
0 01-Jan-21 9.2 True
1 02-Jan-21 9.5 True
2 03-Jan-21 10.1 False
3 04-Jan-21 11.0 False
4 05-Jan-21 10.5 False
5 06-Jan-21 10.2 False
6 07-Jan-21 9.8 True
7 08-Jan-21 8.5 True
8 09-Jan-21 6.2 False
9 10-Jan-21 9.9 True
Один из вариантов, чтобы получить только первый из ряда последовательных False
строк, мы можем выбрать строки, где предыдущая строка True
. Мы можем сделать это, используя shift
, который по умолчанию сдвигает строки вниз на единицу, т. е. строка 0 становится 1, строка 1 становится 2 и т. д.
>>> df.in_range.shift().head()
0 NaN
1 True
2 True
3 False
4 False
Name: in_range, dtype: object
У первой строки нет предыдущей строки, поэтому она заполняется NaN
. Однако в вашем случае нам нужно заполнить его True
. Сохранение этого в другом столбце:
>>> df['in_range_shift'] = df.in_range.shift(fill_value=True)
>>> df.head(10)
Date Temperature in_range in_range_shift
0 01-Jan-21 9.2 True True
1 02-Jan-21 9.5 True True
2 03-Jan-21 10.1 False True # <-
3 04-Jan-21 11.0 False False
4 05-Jan-21 10.5 False False
5 06-Jan-21 10.2 False False
6 07-Jan-21 9.8 True False
7 08-Jan-21 8.5 True True
8 09-Jan-21 6.2 False True # <-
9 10-Jan-21 9.9 True False
Обратите внимание, как мы получаем (False, True)
в последних двух столбцах для каждого значения, которое мы хотим.
Так что просто сделайте:
>>> df[~df.in_range & df.in_range_shift]
Date Temperature in_range in_range_shift
2 03-Jan-21 10.10 False True
8 09-Jan-21 6.20 False True
10 11-Jan-21 10.10 False True
16 17-Jan-21 10.22 False True
Что, конечно, можно сделать гораздо более лаконично с оригиналом df
:
>>> m = df.Temperature.between(7, 10)
>>> df[~m & m.shift(fill_value=True)]
Date Temperature Flag
2 03-Jan-21 10.10 UPPER
8 09-Jan-21 6.20 LOWER
10 11-Jan-21 10.10 UPPER
16 17-Jan-21 10.22 UPPER
@grandpa хорошо, теперь я понял - пожалуйста, рассмотрите мой обновленный / расширенный ответ.
Это идеально - большое спасибо!
Верно, но мне нужны только те дни, когда порог изначально нарушен; не дни на улице. В идеале фильтр вернул бы список, включающий только те флаги, которые я вручную добавил в таблицу данных.