Ответ 1
В настоящее время вы можете сделать это в несколько шагов со встроенным pandas.merge()
и boolean indexing.
merged = df.merge(df2, on='key')
valid = (merged.date >= merged.valid_from) & \
(merged.date <= merged.valid_to)
df['joined_value'] = merged[valid].value_y
(Примечание: столбец value
df2
доступен как value_y
после слияния, поскольку он конфликтует с столбцом с тем же именем в df
, а суффиксы слияния по умолчанию - _x, _y
для левый и правый кадры соответственно.)
Вот пример, с другой установкой, показывающей, как обрабатываются недопустимые даты.
n = 8
dates = pd.date_range('1/1/2013', freq='D', periods=n)
df = DataFrame({'key': np.arange(n),
'date': dates,
'value': np.arange(n) * 10})
df2 = DataFrame({'key': np.arange(n),
'valid_from': dates[[1,1,1,1,5,5,5,5]],
'valid_to': dates[[4,4,4,4,6,6,6,6]],
'value': np.arange(n) * 100})
Вход df2
:
key valid_from valid_to value
0 0 2013-01-02 00:00:00 2013-01-05 00:00:00 0
1 1 2013-01-02 00:00:00 2013-01-05 00:00:00 100
2 2 2013-01-02 00:00:00 2013-01-05 00:00:00 200
3 3 2013-01-02 00:00:00 2013-01-05 00:00:00 300
4 4 2013-01-06 00:00:00 2013-01-07 00:00:00 400
5 5 2013-01-06 00:00:00 2013-01-07 00:00:00 500
6 6 2013-01-06 00:00:00 2013-01-07 00:00:00 600
7 7 2013-01-06 00:00:00 2013-01-07 00:00:00 700
Промежуточная рамка merged
:
date key value_x valid_from valid_to value_y
0 2013-01-01 00:00:00 0 0 2013-01-02 00:00:00 2013-01-05 00:00:00 0
1 2013-01-02 00:00:00 1 10 2013-01-02 00:00:00 2013-01-05 00:00:00 100
2 2013-01-03 00:00:00 2 20 2013-01-02 00:00:00 2013-01-05 00:00:00 200
3 2013-01-04 00:00:00 3 30 2013-01-02 00:00:00 2013-01-05 00:00:00 300
4 2013-01-05 00:00:00 4 40 2013-01-06 00:00:00 2013-01-07 00:00:00 400
5 2013-01-06 00:00:00 5 50 2013-01-06 00:00:00 2013-01-07 00:00:00 500
6 2013-01-07 00:00:00 6 60 2013-01-06 00:00:00 2013-01-07 00:00:00 600
7 2013-01-08 00:00:00 7 70 2013-01-06 00:00:00 2013-01-07 00:00:00 700
Конечное значение df
после добавления столбца joined_value
:
date key value joined_value
0 2013-01-01 00:00:00 0 0 NaN
1 2013-01-02 00:00:00 1 10 100
2 2013-01-03 00:00:00 2 20 200
3 2013-01-04 00:00:00 3 30 300
4 2013-01-05 00:00:00 4 40 NaN
5 2013-01-06 00:00:00 5 50 500
6 2013-01-07 00:00:00 6 60 600
7 2013-01-08 00:00:00 7 70 NaN