Узким местом является конструкция логического ряда / массива, используемого для индексации.
Снижение до NumPy, по-видимому, дает разумное (~ 2x) улучшение производительности.См. Связанные: pd.Timestamp и np.datetime64: взаимозаменяемы ли они для выбранных целей?
# boundaries for testing
mindt = pd.to_datetime('2016-01-01')
maxdt = pd.to_datetime('2017-01-01')
x = ((df['start'] <= mindt) & (df['end'] >= maxdt)).values
y = (df['start'].values <= mindt.to_datetime64()) & (df['end'].values >= maxdt.to_datetime64())
# check results are the same
assert np.array_equal(x, y)
%timeit (df['start'].values <= mindt.to_datetime64()) & (df['end'].values >= maxdt.to_datetime64())
# 55.6 ms per loop
%timeit (df['start'] <= mindt) & (df['end'] >= maxdt)
# 108 ms per loop
Настройка
np.random.seed(0)
def random_dates(start, end, n):
start_u = start.value//10**9
end_u = end.value//10**9
cols = ['start', 'end']
df = pd.DataFrame({col: pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s') for col in cols})
df = pd.DataFrame(np.sort(df.values, axis=1), columns=cols)
df[cols] = df[cols].apply(pd.to_datetime, errors='raise')
return df
# construct a dataframe of random dates
df = random_dates(pd.to_datetime('2015-01-01'), pd.to_datetime('2018-01-01'), 10**7)