Если ваши даты отсортированы, один из способов сделать это быстро - использовать pd.DateTimeIndex.searchsorted
, чтобы найти все совпадающие даты за O[N log N]
время.
Создание некоторых тестовых данных , это может выглядеть примерно так:
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(
{'values': np.random.rand(10)},
index=sorted(np.random.choice(pd.date_range('2019-08-01', freq='T', periods=10000), 10, replace=False))
)
def add_lag(df):
ind = df.index.searchsorted(df.index - pd.DateOffset(1))
out_of_range = (ind <= 0) | (ind >= df.shape[0])
ind[out_of_range] = 0
lag = df['values'].values[ind]
lag[out_of_range] = np.nan
df['lag'] = lag
return df
add_lag(df)
values lag
2019-08-01 06:17:00 0.548814 NaN
2019-08-01 10:51:00 0.715189 NaN
2019-08-01 13:56:00 0.602763 NaN
2019-08-02 09:50:00 0.544883 0.715189
2019-08-03 14:06:00 0.423655 0.423655
2019-08-04 03:00:00 0.645894 0.423655
2019-08-05 07:40:00 0.437587 0.437587
2019-08-07 00:41:00 0.891773 0.891773
2019-08-07 07:05:00 0.963663 0.891773
2019-08-07 15:55:00 0.383442 0.891773
При таком подходе кадр данных с 1 миллионом строк может быть вычислен за десятки миллисекунд:
df = pd.DataFrame(
{'values': np.random.rand(1000000)},
index=sorted(np.random.choice(pd.date_range('2019-08-01', freq='T', periods=10000000), 1000000, replace=False))
)
%timeit add_lag(df)
# 10 loops, best of 3: 71.5 ms per loop
Обратите внимание, что это не находит ближайшее значение с лагом в один день, но ближайшее значение после лагом в один день. Если вам нужно ближайшее значение в любом направлении, вам нужно изменить этот подход.