interval_range и pd.cut с игнорированием Overlapping error

Имеется код, который делит датафрейм на сегменты(колонка n1) в зависимости от колонки linear.

import pandas as pd
import numpy as np
d = {'stores': ['AG21', 'AG41', 'AG85', 'AG45', 
'AG31', 'AS25', 'AR81', 'AA43',
'AG21', 'AD83', 'AA36', 'AG55',
'AT58', 'AD11', 'AH32', 'AE17'], 
'linear': [430, 145 , 120, 180,
250, 250, 250, 320,
376, 390, 420, 580,
350, 190, 125, 390]}
df = pd.DataFrame(data=d)
df = df.sort_values(by='linear')
ints = pd.interval_range(start=df['linear'].min(), periods=6, end=df['linear'].max(), closed='left')
df['ranges'] = pd.cut(df['linear'], bins=ints,labels=False, include_lowest=True)
def fun(x):
    if isinstance(x, float) is True:
        return np.nan
    else:
        return x.right
df['ranges1'] = df['ranges'].apply(fun) 
df['n1'] = (df['ranges1'] != df['ranges1'].shift()).cumsum()
df

При попытке указания closed='both' в interval_range, для отображения нижней и верхней границы в расчете, получаю ошибку:

ValueError: Overlapping IntervalIndex is not accepted.

Нужно так, чтобы последняя строчка в linear тоже учитывалась в диапазоне, а closed='left' не берет ее.


Ответы (1 шт):

Автор решения: CrazyElf

Подозреваю, что проблема в точности представления чисел с плавающей точкой. Ну и в том, что у вас числа прямо на границе интервалов. Как это красиво/правильно вылечить не знаю, но если добавить некий эпсилон к правому краю в pd.interval_range, то последнее значение попадёт в интервал:

end = df['linear'].max() + 1e-12

Вывод:

...
0   AG21    430 [426.66666666666737, 503.3333333333342) 503.333333  5
11  AG55    580 [503.3333333333342, 580.000000000001)   580.000000  6
→ Ссылка