Выбор строк в Pandas с использованием нескольких интервалов (объекты диапазона pd.Interval) - PullRequest
1 голос
/ 21 марта 2020

Мне нужно использовать pd.Interval для выбора записей в нескольких диапазонах бинов.

df = pd.DataFrame({'my_col': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})
df['my_col_bin'] = pd.cut(x=df['my_col'], bins=[0, 3, 6, 9, 12], right=False, include_lowest=True)
    my_col  my_col_bin
0   1   [0, 3)
1   2   [0, 3)
2   3   [3, 6)
3   4   [3, 6)
4   5   [3, 6)
5   6   [6, 9)
6   7   [6, 9)
7   8   [6, 9)
8   9   [9, 12)
9   10  [9, 12)
10  11  [9, 12)

Например, я бы хотел выбрать все записи, попадающие в диапазон [3, 12). Я хотел бы получить следующий вывод, используя один диапазон pd.Interval, без указания условия для каждого интервала отдельно:

2   3   [3, 6)
3   4   [3, 6)
4   5   [3, 6)
5   6   [6, 9)
6   7   [6, 9)
7   8   [6, 9)
8   9   [9, 12)
9   10  [9, 12)
10  11  [9, 12)

Я пробовал следующее, но это не сработало.

df[df['my_col_bin'] == pd.Interval(3, 12, closed='left')]

Следующий выбор работает на одном интервале, но кажется, что pd.Interval не поддерживает несколько диапазонов.

df[df['my_col_bin'] == pd.Interval(3, 6, closed='left')]

Можно ли выбрать диапазон между ячейками без явного указания каждого условия интервала? Существует ли краткий способ выбора без фильтрации для каждого интервала отдельно?

Ответы [ 4 ]

3 голосов
/ 21 марта 2020

Interval.overlaps

Требуется apply, но оказывается довольно быстрым даже для большого DataFrame. (Занимает около 50 мс на 1 миллион строк на моей машине)

m = df['my_col_bin'].apply(lambda x: x.overlaps(pd.Interval(3, 12, closed='left')))

df[m]
    my_col my_col_bin
2        3     [3, 6)
3        4     [3, 6)
4        5     [3, 6)
5        6     [6, 9)
6        7     [6, 9)
7        8     [6, 9)
8        9    [9, 12)
9       10    [9, 12)
10      11    [9, 12)
2 голосов
/ 21 марта 2020

А как насчет выбора этого пути?

df[(df['my_col'] >= 3) & (df['my_col'] < 12)]
1 голос
/ 21 марта 2020

Я использую жесткие отношения между интервалами в вашем столбце my_col_bin и вашим целевым интервалом [3, 12), который просто охватывает 3 интервала этого столбца.

(см. Мой другой ответ на ваш вопрос, касающийся общего случая.)

In[1]: intervals = {interval for interval in df.my_col_bin 
                       if interval.left >= 3 and interval.right <= 12}
In[2]: intervals
{Interval(3, 6, closed='left'),
 Interval(6, 9, closed='left'),
 Interval(9, 12, closed='left')}

или

In[1]: intervals = [pd.Interval(i, i + 3, closed="left") for i in range(3, 10, 3)]
In[2]: intervals
[Interval(3, 6, closed='left'),
 Interval(6, 9, closed='left'),
 Interval(9, 12, closed='left')]
In[3]: df[df.my_col_bin.isin(intervals)]
    my_col my_col_bin
2        3     [3, 6)
3        4     [3, 6)
4        5     [3, 6)
5        6     [6, 9)
6        7     [6, 9)
7        8     [6, 9)
8        9    [9, 12)
9       10    [9, 12)
10      11    [9, 12)
1 голос
/ 21 марта 2020

Вы спросили:

Можно ли выбрать диапазон между ячейками без явного указания каждого условия интервала? Существует ли краткий способ выполнить выборку без фильтрации для каждого интервала отдельно?

В общем случае ответ таков: Нет .

«В общем» означает, что нет ни отношений между отдельными интервалами в вашем столбце (в вашем примере они есть), ни отношения между «целевым» интервалом ([3, 12)) и интервалами в вашем столбце (в вашем примере это тоже).

(см. Мой другой ответ на ваш вопрос, который использует такие отношения в вашем примере.)


Почему?

Pandas интервал не является математическим интервалом (в смысле как непрерывный набор действительных чисел).

Pandas интервал - это просто упорядоченный четверка своих свойств (.left, .right, .closed_left, .closed_right).

Например, ваш интервал [3, 12) является не более чем четверкой (3, 12, True, False).


Какие следствия из этого следуют?

Это означает, что нет заданных операций / отношений s как объединение, пересечение, разность или подмножество. И последнее именно то, что вам нужно.


Как я могу видеть, что интервалы - не что иное, как упомянутые четверки?

Из исходного кода или - косвенно - из предоставленного метода и свойств класса Interval. Все они очень просто получены из упомянутых четверок:

closed_left
closed_right
is_empty
left
length
mid
open_left
open_right
overlaps()
right
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...