Экстремумы в рядах данных
Есть два ряда данных. В них требуется выявить экстремум, но сложность в том, что в одном ряде экстремумы должны выявляться до того момента как в другом столбце появятся новые значения.
То есть если в первом одно значение (или группа значений), то это один экстремум, для другого столбца экстремумы стоит считать от момента их появления и до момента появления новых значений в первом столбце.
Для столбца 1 экстремум максимум, для второго - минимум. При этом, возле каждого экстремума нужно получить первое значение из ряда и последнее. Задачка интересная, но один решить не могу к сожалению. Уверен есть простое решение в пару строк. Покажу пример:
Пример данных: https://dropmefiles.com/ra2ds - полный файл
0 0
0 0
0 22.66
0 22.66
0 22.66
0 22.64
0 22.64
0 22.66
0 22.66
0 22.66
0 0
0 0
0 0
0 0
0 0
22.67 0
0 0
0 0
0 22.65
0 22.65
0 0
0 0
22.68 0
22.67 0
0 0
0 0
22.68 0
22.68 0
22.69 0
0 0
0 0
0 22.67
0 0
0 0
22.69 0
22.68 0
0 0
0 0
Группируем так (просто в качестве примера):
0 0
0 22.66
0 22.66
0 22.66
0 22.64
0 22.64
0 22.66
0 22.66
0 22.66
0 0
22.67 0
0 0
0 22.65
0 22.65
0 0
22.68 0
22.67 0
22.68 0
22.68 0
22.69 0
0 0
0 22.67
0 0
22.69 0
22.68 0
0 0
Итог:
0 22.66 <-- первое значение с которого начинается ряд
0 22.64 <-- максимум для первого столбца и минимум для второго из ряда данных до появления другого ряда в столбце
0 22.66 <-- последнее на что зачинается ряд
22.67 0
22.67 0
22.67 0
0 22.65
0 22.65
0 22.65
22.68 0
22.69 0
22.69 0
0 22.67
0 22.67
0 22.67
22.69 0
22.69 0
22.68 0
Ответы (1 шт):
Если я верно понял условие, то попробовать можно так:
import pandas as pd
df = pd.read_csv('df.csv', header=None, names=['A', 'B'])
df = df[~df.eq(0).all(1)]
df['grp'] = df.groupby(df.index.to_series().diff().ne(1).cumsum()).grouper.group_info[0]
df1 = df.groupby('grp').agg({"A":['first','min', 'last'], "B":['first','max', 'last']})
df1.columns = df1.columns.droplevel(1)
df1 = df1.stack()
res = pd.concat([df1.loc[:,'A'], df1.loc[:,'B']], axis=1, ignore_index=True).reset_index(drop=True)
res, соответственно, будет:
0 1
0 0.00 22.65
1 0.00 22.65
2 0.00 22.65
3 0.00 22.64
4 0.00 22.64
5 0.00 22.64
6 22.65 0.00
7 22.65 0.00
8 22.65 0.00
9 22.64 0.00
10 22.64 0.00
11 22.64 0.00
12 22.65 0.00
13 22.65 0.00
14 22.64 0.00
...
501 0.00 32.73
502 0.00 32.73
503 0.00 32.80
504 0.00 32.62
505 0.00 32.62
506 0.00 32.62
507 0.00 32.58
508 0.00 32.56
509 0.00 32.62
510 33.18 0.00
511 33.50 0.00
512 33.42 0.00
513 0.00 32.91
514 0.00 32.79
515 0.00 32.88
UPDATE
Немного переделал так, чтобы объединить последовательные серии в каждом столбце, как того хочет автор вопроса:
import pandas as pd
df = pd.read_csv('df.csv', header=None, names=['A', 'B'])
df = df[~df.eq(0).all(1)]
df['border'] = ((df['A'] > 0) & (df['A'].shift(1) == 0)|(df['B'] > 0) & (df['B'].shift(1) == 0))
df['group'] = df['border'].cumsum()
df1 = df.groupby('group').agg({"A":['first','max', 'last'], "B":['first','min', 'last']})
df1.columns = df1.columns.droplevel(1)
df1 = df1.stack()
res = pd.concat([df1.loc[:,'A'], df1.loc[:,'B']], axis=1, ignore_index=True).reset_index(drop=True)
Соответственно, res будет:
0 1
0 0.00 22.65
1 0.00 22.64
2 0.00 22.64
3 22.65 0.00
4 22.67 0.00
5 22.67 0.00
6 0.00 22.66
7 0.00 22.66
8 0.00 22.66
9 22.67 0.00
10 22.67 0.00
11 22.67 0.00
. . .
195 33.30 0.00
196 34.19 0.00
197 34.16 0.00
198 0.00 33.65
199 0.00 32.56
200 0.00 32.62
201 33.18 0.00
202 33.50 0.00
203 33.42 0.00
204 0.00 32.91
205 0.00 32.79
206 0.00 32.88