Для небольших фреймов данных Объединение двух фреймов данных на основе даты между двумя другими датами без общего столбца дает хорошее решение.Просто он использует декартово произведение обоих фреймов данных и не будет хорошо масштабироваться с большими фреймами данных.
Возможной оптимизацией будет добавление округленных столбцов даты и времени к фреймам данных и присоединение к ним.эти столбцы.Поскольку объединение намного более эффективно, чем декартово произведение, выигрыш в памяти и времени выполнения должен быть заметен.
То, что вы хотите (псевдокод здесь):
df1.created_at <= df2.created_at and df2.created_at - df1.created_at <= 2mins
Я бы добавилв обоих фреймах данных столбец ref
, определенный как (все еще псевдокод): created_at - (created_at.minute % 2)
Строки в обоих фреймах данных имеют одинаковое значение ссылки, даты должны быть на расстоянии менее 4 минут.Но это не выберет все ожидаемые случаи, потому что даты могут быть ближе, чем 2 минуты и попадают в 2 разных слота.Чтобы справиться с этим, я предлагаю иметь столбец ref2
в df1
, определенный как ref1 + 2minutes
, и выполнить второе объединение на df1.ref == df1.ref2
.Этого будет достаточно, потому что вы хотите, чтобы событие df1 было раньше df2, иначе нам понадобится 3-й столбец ref3 = ref1 - 2minutes
.
Затем, как и в указанном ответе, мы можем выбрать строки, фактически соответствующие требованию, исвяжитесь с двумя соединенными фреймами данных.
Код Pandas может быть:
# create auxilliary columns
df1['ref'] = df1.index - pd.to_timedelta(df1.index.minute % 2, unit='m')
df1['ref2'] = df1.ref + pd.Timedelta(minutes=2)
df2['ref'] = df2.index - pd.to_timedelta(df2.index.minute % 2, unit='m')
df2.index.name = 'created_at_2'
df2 = df2.reset_index().set_index('ref')
# join on ref and select the relevant lines
x1 = df1.join(df2, on='ref', how='inner')
x1 = x1.loc[(x1.index <= x1.created_at_2)
& (x1.created_at_2 - x1.index <= pd.Timedelta(minutes=2))]
# join on ref2 and select the relevant lines
x2 = df1.join(df2, on='ref2', how='inner')
x2 = x2.loc[(x2.index <= x2.created_at_2)
& (x2.created_at_2 - x2.index <= pd.Timedelta(minutes=1))]
# concatenate the partial result and clean the resulting dataframe
merged = pd.concat([x1, x2]).drop(columns=['ref', 'ref2'])
merged.index.name = 'created_at'