简单的迭代方法是O(n*m),其中n = len(df1) 和m = len(df2),因为对于df1 中的每个日期,您必须检查它是否包含在最多m 间隔中。
如果df2定义的间隔不相交,那么理论上有更好的方法:使用searchsorted查找df1中的每个日期在start_dates中的位置,然后再次使用searchsorted找到每个日期在 end_dates 中的位置。当两次调用searchsorted 的索引相等时,日期落在一个区间内。
Searchsorted 假设截止日期已排序并使用二进制搜索,因此每个调用的复杂度为 O(n*log(m))。
如果m足够大,使用searchsorted应该会更快
比天真的迭代方法。
如果m 不大,迭代的方法可能会更快。
这里是一个例子,使用searchsorted:
import numpy as np
import pandas as pd
Timestamp = pd.Timestamp
df1 = pd.DataFrame({'date': (Timestamp('2012-08-01'),
Timestamp('2012-08-02'),
Timestamp('2012-08-03'),
Timestamp('2012-10-29'),
Timestamp('2012-10-30'),
Timestamp('2012-11-01'),
Timestamp('2012-10-15'), # on then end_date
Timestamp('2012-09-04'), # outside an interval
Timestamp('2012-09-05'), # on then start_date
),
'value': (82, 20, 94, 58, 73, 1, 2, 3, 4)})
print(df1)
df2 = pd.DataFrame({'end_date': (
Timestamp('2012-10-15'),
Timestamp('2012-09-04'),
Timestamp('2012-11-01')),
'other_value': ("foo", "bar", "foobar"),
'start_date': (
Timestamp('2012-09-05'),
Timestamp('2012-08-01'),
Timestamp('2012-10-16'))})
df2 = df2.reindex(columns=['start_date', 'end_date', 'other_value'])
df2.sort(['start_date'], inplace=True)
print(df2)
# Convert to DatetimeIndexes so we can call the searchsorted method
date_idx = pd.DatetimeIndex(df1['date'])
start_date_idx = pd.DatetimeIndex(df2['start_date'])
# Add one to the end_date so the original end_date will be included in the
# half-open interval.
end_date_idx = pd.DatetimeIndex(df2['end_date'])+pd.DateOffset(days=1)
start_idx = start_date_idx.searchsorted(date_idx, side='right')-1
end_idx = end_date_idx.searchsorted(date_idx, side='right')
df1['idx'] = np.where(start_idx == end_idx, end_idx, np.nan)
result = pd.merge(df1, df2, left_on=['idx'], right_index=True)
result = result.reindex(columns=['idx', 'date', 'value', 'other_value'])
print(result)
df1 等于
date value
0 2012-08-01 82
1 2012-08-02 20
2 2012-08-03 94
3 2012-10-29 58
4 2012-10-30 73
5 2012-11-01 1
6 2012-10-15 2
7 2012-09-04 3
8 2012-09-05 4
和df2 等于
start_date end_date other_value
1 2012-08-01 2012-09-04 bar
0 2012-09-05 2012-10-15 foo
2 2012-10-16 2012-11-01 foobar
以上代码产生
idx date value other_value
0 0 2012-08-01 82 foo
1 0 2012-08-02 20 foo
2 0 2012-08-03 94 foo
7 0 2012-09-04 3 foo
3 2 2012-10-29 58 foobar
4 2 2012-10-30 73 foobar
5 2 2012-11-01 1 foobar
6 1 2012-10-15 2 bar
8 1 2012-09-05 4 bar