Найти перекрывающиеся метки времени с помощью панд - PullRequest
0 голосов
/ 17 октября 2018

У меня есть фрейм данных, содержащий время начала, время окончания и транзакции, например:

    tid       starttime        endtime
0   0.0     1537204247.00   1537204309.00
1   1.0     1537204248.00   1537204309.00
2   21.0    1537207170.00   1537207196.00

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

p['overlap'] = False # This is my original dataframe

def compute_overlaps(df):
    for i, row_curr in df.iterrows():
        if( p.loc[row_curr['ix']]['overlap'] != True ):
            overlap_indexes = df[(row_curr['ix'] != df['ix']) & (row_curr['starttime'] < df['endtime']) & (df['starttime'] < row_curr['endtime'])].index
            p['overlap'].loc[row_curr['ix']] = True
            p['overlap'].loc[overlap_indexes] = True

<p_grouped_by_something>.apply(compute_overlaps)

Вывод:

    tid       starttime        endtime     overlap
0   0.0     1537204247.00   1537204309.00   True
1   1.0     1537204248.00   1537204309.00   True
2   21.0    1537207170.00   1537207196.00   False

Обратите внимание, что для каждой транзакции мне просто нужно определить,он перекрывается с не более еще одной транзакцией.Если он найден, мне не нужно проверять все остальные транзакции;Я могу остановиться на этом и пометить его как перекрывающийся.

Изначально у меня был вложенный цикл for, использующий iterrows, который был ужасно медленным.Затем я смог векторизовать внутренний цикл, но внешний цикл остался.Есть ли способ векторизовать все вычисления, чтобы они выполнялись быстрее?

1 Ответ

0 голосов
/ 17 октября 2018

Вы можете использовать numpy boradcast

s1=df.starttime.values
s2=df.endtime.values
sum(np.minimum(s2[:,None],s2)-np.maximum(s1[:,None],s1)>0)>1
Out[36]: array([ True,  True, False])

Объяснение:

1-й: оверлей для диапазона

(x1, y1) с (x2, y2)min (y2, y1) -max (x1, x2)> 0, тогда два диапазона перекрываются

2-й: почему нужно больше 2, поскольку я использовал numpy braod cast, поэтому диагональ всегда представляла себясравнениеТогда нам нужно больше двух.

Обновление:

Если у вас есть df и split df1 .... dfn (посмотрите на np.split)

s1=df.starttime.values
s2=df.endtime.values
l=[df1,df2,df3,df4,df5...]
n=[]
for  x in l: 
       n.append(sum(np.minimum(s2[:,None],x.values)-np.maximum(s1[:,None],x.values)>0)>1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...