Как найти интервал с наибольшим перекрытием в pandas - PullRequest
0 голосов
/ 16 июня 2020

Предположим, у меня есть четыре интервала:

a = pd.Interval(0, 2)
b = pd.Interval(1, 2)
c = pd.Interval(0, 1.1)
d = pd.Interval(-1,-0.5)

Наиболее частое / частое перекрытие составляет от 1 до 1,1, поскольку оно покрывается всеми a, b и c (тремя из четыре выше).

Как я могу найти это, учитывая список из N интервалов? В идеале мне нужна функция, которая может принимать список из 4 вышеуказанных интервалов и возвращать pd.Interval(1, 1.1) в качестве вывода.

1 Ответ

1 голос
/ 16 июня 2020

Я предположил, что вы пытаетесь получить интервал, который содержится в большинстве других интервалов, потому что интервал с наиболее частыми перекрытиями - (-1,1.1] вместо (1,1.1], я не знаю, может быть, я ошибаюсь, но используя pd.IntervalsIndex.overlaps Я получил это:

import pandas as pd
from itertools import product

a = pd.Interval(0, 2)
b = pd.Interval(1, 2)
c = pd.Interval(0, 1.1)
d = pd.Interval(-1,-0.5)
ls=[a,b,c,d]
indexinter = pd.IntervalIndex(ls)
print(indexinter.overlaps(pd.Interval(1, 1.1)))
print('Interval (1,1.1] overlaps ',sum(indexinter.overlaps(pd.Interval(1, 1.1))),' of 4')
print('\n')
print(indexinter.overlaps(pd.Interval(-1, 1.1)))
print('Interval (-1,1.1] overlaps ',sum(indexinter.overlaps(pd.Interval(-1, 1.1))),' of 4')

Вывод:

[ True  True  True False]
Interval (1,1.1] overlaps  3  of 4


[ True  True  True  True]
Interval (-1,1.1] overlaps  4  of 4

Безусловно, чтобы получить интервал, который содержится в большинстве других интервалов , вы можете попробовать следующее:

Первый вариант

import pandas as pd
import portion as P

d = pd.Interval(0, 2)
b = pd.Interval(1, 2)
c = pd.Interval(0, 1.1)
a = pd.Interval(-1,-0.5)

def getmaxoverlapwrap(ls,inter):
    intervals=[P.openclosed(i.left, i.right) for i in ls]
    for i in intervals[1:]:
        newinter=inter&i
        if newinter.empty==False:
            inter=newinter     
    return inter
def getmaxoverlap(ls):
    intervals=[P.openclosed(i.left, i.right) for i in ls]
    ls1=[getmaxoverlapwrap(ls,i) for i in intervals]
    index = list(map(lambda x: sum([(x in s) for s in ls]), ls1)).index(max(list(map(lambda x: sum([(x in s) for s in ls]), ls1))))
    return ls1[index]
ls=[a,b,c,d]
indexinter = pd.IntervalIndex(ls)
print(getmaxoverlap(ls))

Вам необходимо установить библиотеку portion (ранее распространялась как python -интервалы), то есть библиотека, которая предоставляет нам структуру данных и операции для интервалов в Python 3.5+, такие как: -Поддержка интервалов любых (сопоставимых) объектов, -закрытых или открытых, конечных или (полубесконечных) интервалов, -наборов интервалов (объединение of atomi c интервалы) поддерживаются, -автоматически c упрощение интервалов, et c.

второй вариант

import pandas as pd
from itertools import product

a = pd.Interval(0, 2)
b = pd.Interval(1, 2)
c = pd.Interval(0, 1.1)
d = pd.Interval(-1,-0.5)

def getmostcontained(ls):
    indexinter = pd.IntervalIndex([pd.Interval(inter.left, inter.right, closed='both') for inter in ls])
    rights = [i.right for i in ls]
    lefts=[i.left for i in ls]
    allcomb = [pd.Interval(i[0],i[1]) for i in list(set(list(product(lefts, rights)))) if i[0]<=i[1]]
    count=0
    maxi=sum(indexinter.contains(allcomb[0].left))+sum(indexinter.contains(allcomb[0].right))
    for i in allcomb:
        newmaxi=sum(indexinter.contains(i.left))+sum(indexinter.contains(i.right))

        if newmaxi>maxi:
            count=allcomb.index(i)

    return allcomb[count]

ls=[a,b,c,d]
print(getmostcontained(ls))

третий вариант

import pandas as pd

a = pd.Interval(0, 2)
b = pd.Interval(1, 2)
c = pd.Interval(0, 1.1)
d = pd.Interval(-1,-0.5)

def getmaxoverlap(ls):
    indexinter = pd.IntervalIndex(ls)
    start=ls[0].left
    end=ls[0].right
    checkstart=sum(indexinter.contains(start+0.00000000099))
    checkend=sum(indexinter.contains(end))


    for i in ls:
        if sum(indexinter.contains(i.left+0.000000000099))>checkstart:
            checkstart=sum(indexinter.contains(i.left+0.000000000099))
            start=i.left
        if sum(indexinter.contains(i.right))>checkend:
            checkend=sum(indexinter.contains(i.right))
            end=i.right

    return pd.Interval(start, end)

ls=[a,b,c,d]
print(getmostcontained(ls))            

Вывод всех вариантов:

(1,1.1]

Первый вариант потребовалось 0.025967300000047544 seconds для 100-кратного запуска сценария и 27.19270740000138 seconds для запуска 100000-кратного сценария, второй вариант потребовал 0.15769210000144085 seconds для запуска 100-кратного сценария и 115.13360900000043 seconds для запуска 100000-кратного сценария, и третий вариант потребовал 0.08970480000061798 seconds для 100-кратного выполнения сценария и 107.52801619999991 seconds для выполнения 100000-кратного выполнения сценария. Разница, может быть, почти не заметна, по крайней мере, для второго и третьего вариантов, но вот отметки времени, которые я получил, чтобы вы знали и выбираете один.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...