Это мой DataFrame:
import pandas as pd
df = pd.DataFrame(
{
'a': [3, 1, 2, 5, 10, 3, 13, 3, 2],
}
)
Ожидаемый результат — создание a_max
и a_min
:
a a_max a_min
0 3 NaN NaN
1 1 3 1
2 2 3 1
3 5 3 1
4 10 3 1
5 3 10 3
6 13 10 3
7 3 13 3
8 2 13 2
Логика:
Я объясняю логику построчно. Для этого существует динамическое окно df
, в котором для первого экземпляра окна рассматривается только первая строка. Для второго экземпляра окна рассматриваются первые две строки. То же, что и ниже:
Это первые четыре окна. Соответственно, он расширяется.
Для каждого окна мне нужно найти максимальное значение, а после этого мне нужно найти минимальное значение НИЖЕ этого максимального значения.
Я начинаю объяснять это из желтого окна. Для этого окна максимальное значение равно 3, а минимальное значение НИЖЕ равно 1. Вот почему a_max
и a_min
для этого окна равны 3 и 1.
Теперь для оранжевого окна максимальное значение равно 5, но поскольку в этом окне нет значений НИЖЕ этого значения, меньшего 5, предыдущие a_max
и a_min
повторяются.
И логика продолжается для остальных строк.
Это моя попытка:
df['a_max'] = df.a.cummax()
df['a_min'] = df.a.cummin()
@mozway Удивительно, как ты их решаешь. УХ ТЫ.
Мне чаще всего нравятся ваши вопросы, они, как правило, достаточно сложны, чтобы их было интересно решать, и достаточно общие, чтобы их можно было отнести к SO.
@mozway Для меня большая честь поговорить с тобой :)
Это сложный вопрос, я бы использовал сдвиг cummax + , затем маску + ffill для вычисления a_max
. Тогда a_min
— это groupby.cummin на группу идентичных a_max
:
# compute the shifted cummax
cm = df['a'].cummax().shift()
# a_max is the cummax except if the current row is larger
df['a_max'] = cm.mask(df['a'].gt(cm)).ffill()
# a_min is the cummin of the current group of a_max
df['a_min'] = df.groupby('a_max')['a'].cummin()
Выход:
a a_max a_min
0 3 NaN NaN
1 1 3.0 1.0
2 2 3.0 1.0
3 5 3.0 1.0
4 10 3.0 1.0
5 3 10.0 3.0
6 13 10.0 3.0
7 3 13.0 3.0
8 2 13.0 2.0
Промежуточные продукты:
a a_max cummax shift mask ffill a_min
0 3 NaN 3 NaN NaN NaN NaN
1 1 3.0 3 3.0 3.0 3.0 1.0
2 2 3.0 3 3.0 3.0 3.0 1.0
3 5 3.0 5 3.0 NaN 3.0 1.0
4 10 3.0 10 5.0 NaN 3.0 1.0
5 3 10.0 10 10.0 10.0 10.0 3.0
6 13 10.0 13 10.0 NaN 10.0 3.0
7 3 13.0 13 13.0 13.0 13.0 3.0
8 2 13.0 13 13.0 13.0 13.0 2.0
Я немного упростил решение,
expanding.min
на самом деле простоcummin